From 601c63513b810c4f068eb596291bb0cd5fdef8b2 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 04:59:48 +0200 Subject: [PATCH 01/33] Cleanup --- .github/CODEOWNERS | 1 - .github/workflows/bump-version-pr.yaml | 30 ----------------- .github/workflows/feature-request.yml | 43 ------------------------ .github/workflows/info-needed-closer.yml | 27 --------------- .github/workflows/locker.yml | 24 ------------- 5 files changed, 125 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/bump-version-pr.yaml delete mode 100644 .github/workflows/feature-request.yml delete mode 100644 .github/workflows/info-needed-closer.yml delete mode 100644 .github/workflows/locker.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index f426a03c5..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @Microsoft/vscodeazuretoolsdev diff --git a/.github/workflows/bump-version-pr.yaml b/.github/workflows/bump-version-pr.yaml deleted file mode 100644 index dec36e0a9..000000000 --- a/.github/workflows/bump-version-pr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Bump version after release - -# Run when release is published, or manually triggered -on: - release: - types: [published] - workflow_dispatch: - -jobs: - bump: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Bump version - id: bump - uses: alexweininger/bump-prerelease-version@v0.1.1 - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - title: ${{ env.MESSAGE }} - body: Automatically created by ${{ env.RUN_LINK }} - commit-message: ${{ env.MESSAGE }} - branch: bot/bump-${{ steps.bump.outputs.new-version }} - base: main - author: GitHub - env: - RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - MESSAGE: Bump version after release diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml deleted file mode 100644 index 94c0c5144..000000000 --- a/.github/workflows/feature-request.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Feature Request Manager -on: - issues: - types: [milestoned] - schedule: - - cron: 15 5 * * * # 10:15pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: actions/checkout@v3 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - run: npm install --production --prefix ./actions - - name: Run Feature Request Manager - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: ./actions/feature-request - with: - token: ${{secrets.AZCODE_BOT_PAT}} - candidateMilestoneID: 28 - candidateMilestoneName: "Backlog Candidates" - backlogMilestoneID: 33 - featureRequestLabel: "feature" - upvotesRequired: 5 - numCommentsOverride: 10 - initComment: "This feature request is now a candidate for our backlog. The community has 240 days to upvote the issue. If it receives 5 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectComment: ":slightly_frowning_face: In the last 60 days, this issue has received less than 5 community upvotes and we closed it. Still a big Thank You to you for taking the time to create it! To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectLabel: "out of scope" - warnComment: "This issue has become stale and is at risk of being closed. The community has 60 days to upvote the issue. If it receives 5 upvotes we will keep it open and take another look. If not, we will close it. To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - labelsToExclude: "P0,P1" - acceptComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - warnDays: 60 - closeDays: 240 - milestoneDelaySeconds: 60 - diff --git a/.github/workflows/info-needed-closer.yml b/.github/workflows/info-needed-closer.yml deleted file mode 100644 index 9304007a4..000000000 --- a/.github/workflows/info-needed-closer.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Info Needed Closer -on: - schedule: - - cron: 30 5 * * * # 10:30pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Info Needed Closer - uses: ./actions/needs-more-info-closer - with: - token: ${{secrets.AZCODE_BOT_PAT}} - label: info-needed - closeDays: 14 - closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/azcodeissuereporting) guidelines.\n\nHappy Coding!" - pingDays: 80 - pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information." diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml deleted file mode 100644 index 050406703..000000000 --- a/.github/workflows/locker.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Locker -on: - schedule: - - cron: 0 5 * * * # 10:00pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Locker - uses: ./actions/locker - with: - token: ${{secrets.AZCODE_BOT_PAT}} - daysSinceClose: 45 - daysSinceUpdate: 7 From 9eb04d16adf195ac24f49f1e4e28866431158b72 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 06:05:45 +0200 Subject: [PATCH 02/33] squash! --- .nvmrc | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 0cf077e6b..000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -16.14 From ef0868c76bc326307604bdc11fbd1a2da90709c6 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 07:39:51 +0200 Subject: [PATCH 03/33] squash! --- CHANGELOG.md | 404 - CODE_OF_CONDUCT.md | 9 - SECURITY.md | 41 - SUPPORT.md | 9 - package-lock.json | 21347 ------------------------------------------- package.json | 106 +- 6 files changed, 53 insertions(+), 21863 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 CODE_OF_CONDUCT.md delete mode 100644 SECURITY.md delete mode 100644 SUPPORT.md delete mode 100644 package-lock.json diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 6eab12dcc..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,404 +0,0 @@ -# Change Log - -## 0.20.0 - -This release adds the initial Azure AD authentication support for PostgreSQL flexible database servers and fixed various bugs. See [0.20.0](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.20.0+is%3Aclosed+) for all closed issues. - -### Breaking change - -- The extension is migrated to use vscode secretStorage module for storing user credentials [#2137](https://github.com/microsoft/vscode-cosmosdb/issues/2137). If you have local attachments that are broken due to this change, please re-attach them. -- The CosmosDB Graph extension has been removed from the marketplace. Attempting to open the graph explorer will open a documentation suggesting alternative tools for viewing graphs [#2086](https://github.com/microsoft/vscode-cosmosdb/issues/2086). - -### Added - -- The extension now supports connecting to PostgreSQL flexible database server as Azure AD users. Read this [wiki](https://aka.ms/postgresql-passwordless-wiki) to learn more. - -## 0.19.4 - 2023-05-17 - -### Added -* Add support for the upcoming Azure Resources Focus feature - -## 0.19.3 - 2023-02-15 - -### Added -* Forward compatibility with Azure Resources API v2 @alexweininger in [#2095](https://github.com/microsoft/vscode-cosmosdb/pull/2095) - -### Changed -* Remove Preview label for Postgres Flexible by @tonybaloney in [#2058](https://github.com/microsoft/vscode-cosmosdb/pull/2058) -* Fix revealing attached database by @alexweininger in [#2092](https://github.com/microsoft/vscode-cosmosdb/pull/2092) - -### Engineering -* Remove version checker action by @alexweininger in [#2046](https://github.com/microsoft/vscode-cosmosdb/pull/2046) -* Replace public-ip with our own util to fix CVE-2022-33987 by @alexweininger in [#2048](https://github.com/microsoft/vscode-cosmosdb/pull/2048) -* Migrate to vscode-azext-dev by @alexweininger in [#2050](https://github.com/microsoft/vscode-cosmosdb/pull/2050) -* Update AppInsights key by @bwateratmsft in [#2052](https://github.com/microsoft/vscode-cosmosdb/pull/2052) -* Add post release version bumper by @alexweininger in [#2053](https://github.com/microsoft/vscode-cosmosdb/pull/2053) -* Use shared Azure Id parsing utils by @alexweininger in [#2054](https://github.com/microsoft/vscode-cosmosdb/pull/2054) -* Rename info-needed-closer by @bwateratmsft in [#2056](https://github.com/microsoft/vscode-cosmosdb/pull/2056) -* Move workflow from root to workflows folder by @alexweininger in [#2057](https://github.com/microsoft/vscode-cosmosdb/pull/2057) -* Change filter for treeItemPicker by @nturinski in [#2063](https://github.com/microsoft/vscode-cosmosdb/pull/2063) -* Finalize CodeQL settings by @bwateratmsft in [#2068](https://github.com/microsoft/vscode-cosmosdb/pull/2068) -* Fix readme badges by @bwateratmsft in [#2070](https://github.com/microsoft/vscode-cosmosdb/pull/2070) -* Skip test suite to enable CodeQL build by @nturinski in [#2081](https://github.com/microsoft/vscode-cosmosdb/pull/2081) -* Add .nvmrc file by @alexweininger in [#2085](https://github.com/microsoft/vscode-cosmosdb/pull/2085) -* Use updated AzExtTreeFileSystem by @alexweininger in [#2094](https://github.com/microsoft/vscode-cosmosdb/pull/2094) - -### Dependencies -* Bump extension version post release by @alexweininger in [#2045](https://github.com/microsoft/vscode-cosmosdb/pull/2045) -* Bump moment from 2.29.2 to 2.29.4 by @dependabot in [#2049](https://github.com/microsoft/vscode-cosmosdb/pull/2049) -* Bump loader-utils from 1.4.0 to 1.4.2 by @dependabot in [#2077](https://github.com/microsoft/vscode-cosmosdb/pull/2077) -* Bump yargs-parser and yargs by @dependabot in [#2078](https://github.com/microsoft/vscode-cosmosdb/pull/2078) -* Bump decode-uri-component from 0.2.0 to 0.2.2 by @dependabot in [#2083](https://github.com/microsoft/vscode-cosmosdb/pull/2083) -* Bump qs from 6.10.1 to 6.11.0 by @dependabot in [#2084](https://github.com/microsoft/vscode-cosmosdb/pull/2084) -* Bump @xmldom/xmldom from 0.7.5 to 0.7.8 by @dependabot in [#2074](https://github.com/microsoft/vscode-cosmosdb/pull/2074) -* Bump flat and mocha by @dependabot in [#2088](https://github.com/microsoft/vscode-cosmosdb/pull/2088) -* Bump json5 from 1.0.1 to 1.0.2 by @dependabot in [#2089](https://github.com/microsoft/vscode-cosmosdb/pull/2089) - -## 0.19.2 - 2022-06-30 - -### Changed -- Update @vscode/extension-telemetry to 0.6.2 [#2042](https://github.com/microsoft/vscode-cosmosdb/pull/2042) - -## 0.19.1 - 2022-06-01 - -### Changed -- Update @vscode/extension-telemetry to 0.5.2 [#2032](https://github.com/microsoft/vscode-cosmosdb/pull/2032) - -## 0.19.0 - 2022-05-24 - -We've made some large design changes to the Azure extensions for VS Code. [View App Centric release notes](https://aka.ms/AzCode/AppCentric) -### Changed -- Minimum version of VS Code is now 1.57.0 - -## 0.18.1 - 2021-08-11 -### [Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/32?closed=1) -- Fixed the ETIMEDOUT issue when signing into a PostgreSQL Flexible server on multiple machines - -## 0.18.0 - 2021-07-21 -### Added -- Postgres Flexible Servers (Preview) includes support for Databases, Functions and Stored Procedures - -### Changed -- Postgres Single Server defaults to version "11" - -### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/26?closed=1) - -## 0.17.0 - 2021-06-22 -### Added -- SKU type option is now available while creating PostgreSQL servers -- Option to select either "Provisioned throughput" or "Serverless" model while creating CosmosDB accounts - -### Changed -- Icons updated to match VS Code's theme. Install new product icon themes [here](https://marketplace.visualstudio.com/search?term=tag%3Aproduct-icon-theme&target=VSCode) - -### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/30?closed=1) - -## 0.16.0 - 2021-02-23 -### Added -- Now depends on the "Azure Resources" extension, which provides a "Resource Groups" and "Help and Feedback" view -- Grouped items in all context menus to improve access and readability -- "Attached Emulator..." option added to Attach Database Accounts context menu - -### Changed -- "Report an Issue" button was removed from errors. Use the "Help and Feedback" view or command palette instead - -### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/29?closed=1) - -## 0.15.1 - 2020-12-04 -### Added -- Newly created Azure CosmosDB - MongoDB servers default to version “3.6” - -### Changed -- Minimum version of VS Code is now 1.48.0 -- Improved extension activation time (by switching to the azure-sdk-for-js) - -### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/25?closed=1) - -## 0.15.0 - 2020-09-15 -### Added -- Attach PostgreSQL servers by connection string -- PostgreSQL support for integration with App Service extension - -### Changed -- PostgreSQL server defaults to version "10" - -### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.15.0+is%3Aclosed) - -## 0.14.0 - 2020-07-14 -### Added -- Use the setting "azureDatabases.batchSize" to configure the Mongo "DBQuery.shellBatchSize" attribute and the batch size when loading children in the tree view. -- Create and edit stored procedures in PostgreSQL. NOTE: only applies to PostgreSQL server versions 11 and above. - -### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.14.0+is%3Aclosed) - -### Changed -- Results from executing most Mongo commands open in a single read-only editor. - -## 0.13.0 - 2020-05-28 -In this release, we're rebranding the Cosmos DB Extension to Azure Databases to expand our database support beyond just Cosmos DB. This release also marks the first new database engine: PostgreSQL with other database engines coming later this year. -### Added -- PostgreSQL support - - Create and view PostgreSQL servers, databases, and functions. - - Create, edit, and execute PostgreSQL queries - -### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.13.0+is%3Aclosed) - -### Changed -- Viewing and querying Azure Cosmos DB graphs has been moved to a separate graph-specific extension, [vscode-cosmosdbgraph](https://github.com/microsoft/vscode-cosmosdbgraph) - -## 0.12.2 - 2020-03-10 -### Fixed -- Language client is not ready yet [#1334](https://github.com/microsoft/vscode-cosmosdb/issues/1334) - -## 0.12.1 - 2020-01-22 -### Fixed -- When updating a Mongo document, the operation would fail with the following error: `update operation document must contain atomic operators.` [#1298](https://github.com/microsoft/vscode-cosmosdb/issues/1298) -- When importing a `.json` document into a Mongo collection, it would throw the following error: `Error: r.insertedIds is not iterable` [#1307](https://github.com/microsoft/vscode-cosmosdb/issues/1307) - -## 0.12.0 - 2020-01-16 -### Added -- Support for Private Endpoint Connections -- Collapse All button for Cosmos DB explorer - -### Fixed -- When using `find()` in MongoScrapbooks, it would not work properly with chained commands [#981](https://github.com/microsoft/vscode-cosmosdb/issues/981) -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/18?closed=1) - -## 0.11.0 - 2019-09-03 -### Added -- Add `mongo.shell.args` setting to allow passing arguments to mongo shell [#1104](https://github.com/Microsoft/vscode-cosmosdb/issues/1104), [#1126](https://github.com/Microsoft/vscode-cosmosdb/issues/1126) - -### Changed -- Due to a change in the Azure Cosmos DB Emulator, users must explicitly enable the Mongo DB port when starting the emulator. Updated error messages to point to debugging tips at https://aka.ms/AA5zah5. [#1137](https://github.com/microsoft/vscode-cosmosdb/issues/1137), [#1000](https://github.com/microsoft/vscode-cosmosdb/issues/1000) - -### Fixed -- Better shell error handling, add mongo.shell.args setting [#1101](https://github.com/Microsoft/vscode-cosmosdb/issues/1101), [#1092](https://github.com/Microsoft/vscode-cosmosdb/issues/1092), [#1071](https://github.com/Microsoft/vscode-cosmosdb/issues/1071), [#988](https://github.com/Microsoft/vscode-cosmosdb/issues/988), [#838](https://github.com/Microsoft/vscode-cosmosdb/issues/838), [#820](https://github.com/Microsoft/vscode-cosmosdb/issues/820) -- Increase mongo.shell.timeout default value from 5 to 30 [#1115](https://github.com/Microsoft/vscode-cosmosdb/issues/1115) -- Fix document save prompt message [#1021](https://github.com/Microsoft/vscode-cosmosdb/issues/1021) - -## 0.10.2 - 2019-05-01 -### Fixed -- Handle opening resources to use native vscode APIs -- Running the extension in older versions of VS Code -- Report an issue opening a blank webpage due to a large stack frame - -## 0.10.1 - 2019-03-26 -### Added -- Wizards are more informative and allow you to redo some steps - -### Fixed -- Graph views moved from using previewHtml (deprecated) to Webview API - -## 0.10.0 - 2019-02-13 -### Added -* Improved startup and installation performance - -### Fixed -* Accounts created in portal are not recognized as graph/mongo by the extension [#1018](https://github.com/Microsoft/vscode-cosmosdb/issues/1018) -* Confusing error message when running 'Import Document into a Collection' with no Workspace opened [#961](https://github.com/Microsoft/vscode-cosmosdb/issues/961) -* Improve emulator connection error messages [#1016](https://github.com/Microsoft/vscode-cosmosdb/issues/1016) - -## 0.9.1 - 2018-11-28 -### Added -- API support for integration with [App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) -- Multiple documents, collections, or stored procedures can be viewed/edited at once (thanks [@tec-goblin](https://github.com/tec-goblin)) - -### [Fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.9.1+label%3Abug+is%3Aclosed) -- Refresh button doesn't refresh attached accounts [#904](https://github.com/Microsoft/vscode-cosmosdb/issues/904) -- Some scrapbook parse errors were causing an error alert [#959](https://github.com/Microsoft/vscode-cosmosdb/pull/959) -- Downgrade event-stream version due to [event-stream#116](https://github.com/dominictarr/event-stream/issues/116) - -## 0.9.0 - 2018-11-05 -### Added -- Mongo - - Support for [ObjectId, ISODate](https://github.com/Microsoft/vscode-cosmosdb/issues/769) and [regular expression](https://github.com/Microsoft/vscode-cosmosdb/issues/786) [(/pattern/flag)](https://github.com/Microsoft/vscode-cosmosdb/issues/667) syntax in the scrapbook - - Support for [method chaining](https://github.com/Microsoft/vscode-cosmosdb/issues/785). - - Ability to [change timeout](https://github.com/Microsoft/vscode-cosmosdb/issues/809) for commands in scrapbook -- Support [importing documents](https://github.com/Microsoft/vscode-cosmosdb/issues/404) into CosmosDB and Mongo databases. -- Support for [soveriegn clouds](https://github.com/Microsoft/vscode-cosmosdb/commit/5b573f535cdeba109d7ff037b914575e0172c6bd) -- Support creation of fixed collections and graphs [#295](https://github.com/Microsoft/vscode-cosmosdb/issues/295) and [#504](https://github.com/Microsoft/vscode-cosmosdb/issues/504) - -### Fixed -- Collections having two documents of the same id will render properly [#588](https://github.com/Microsoft/vscode-cosmosdb/issues/588) and [#892](https://github.com/Microsoft/vscode-cosmosdb/issues/892) -- Some UI fixes [#576](https://github.com/Microsoft/vscode-cosmosdb/issues/576) and [#873](https://github.com/Microsoft/vscode-cosmosdb/issues/873) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/milestone/16?closed=1) - -### Thank you -A big thank you to the following contributors that helped make the extension even better! -- [Nicolas Kyriazopuolos-Panagiotopoulos @tec-goblin](https://github.com/tec-goblin): - - Updates to a collection now update the corresponding tree item [PR#856](https://github.com/Microsoft/vscode-cosmosdb/pull/856) - - Uploading a document by closing it no longer tries to update the closed editor [PR#818](https://github.com/Microsoft/vscode-cosmosdb/pull/818) - - Fixing tslint issues [PR#829](https://github.com/Microsoft/vscode-cosmosdb/pull/829) - - Use consistent language for various commands [PR#828](https://github.com/Microsoft/vscode-cosmosdb/pull/828) - - Fix some typos [PR#810](https://github.com/Microsoft/vscode-cosmosdb/pull/810) and [PR#816](https://github.com/Microsoft/vscode-cosmosdb/pull/816) -- [Nguyen Long Nhat @torn4dom4n](https://github.com/torn4dom4n), for updating our tasks [PR#887](https://github.com/Microsoft/vscode-cosmosdb/pull/887) - -## 0.8.0 - 2018-07-05 -### Added -- Improved scrapbook experience with better error handling. We now [highlight errors on the scrapbook as you type](https://github.com/Microsoft/vscode-cosmosdb/issues/471)! -- See your [stored procedures for graph accounts](https://github.com/Microsoft/vscode-cosmosdb/issues/422) too! -- [Document labels](https://github.com/Microsoft/vscode-cosmosdb/issues/381) in the tree view are now more descriptive. - -### Fixed -- Scrapbook: can now parse commands with [single quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467) or [no quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467). Examples from the mongo docs should now work when directly pasted. -- Fewer timeout errors on [running commands in the emulator](https://github.com/Microsoft/vscode-cosmosdb/pull/731). -- We correctly parse [collection names with dots](https://github.com/Microsoft/vscode-cosmosdb/issues/666) -- Invalid database accounts will not [prevent the tree from loading](https://github.com/Microsoft/vscode-cosmosdb/issues/628) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?page=1&q=is%3Aissue+milestone%3A0.8.0+is%3Aclosed) - -## 0.7.2 - 2018-06-08 - -### Added -- [Support DNS Seedlist Connection Format](https://github.com/Microsoft/vscode-cosmosdb/pull/670) for mongo connection strings (mongodb+srv://). Thanks [@plusn-nuri](https://github.com/plusn-nuri)! - -### Fixed -- [Support for Extended JSON in scrapbook queries](https://github.com/Microsoft/vscode-cosmosdb/issues/621) -- [Updating mongo documents without an ObjectID in the ID field ](https://github.com/Microsoft/vscode-cosmosdb/issues/534) -- [Log of fixed bugs](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.7.2+is%3Aclosed) - -## 0.7.1 - 2018-05-10 - -### [Fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.1%22+is%3Aclosed+label%3Abug) - -- Fixed error "Unexpected Experience Value" when retrieving database accounts - -## 0.7.0 - 2018-05-04 - -### Added -- Mongo - - CodeLens support for scrapbook - - Execute all commands in a scrapbook, allowing you to use scrapbooks as scripts - - Support for ObjectIDs, ISODate, and extended JSON data types in document views - -- SQL - - View, open, edit and update Stored Procedures - -- Miscellaneous - - Error messages are now modal - - Open newly created docs in editor - -### Changed -- Moved Azure CosmosDB Explorer to new Azure view container instead of file explorer - -### Fixed -- [Better error messages for connection strings](https://github.com/Microsoft/vscode-cosmosdb/pull/600) -- [Don't throw errors on dropping non-existent collections](https://github.com/Microsoft/vscode-cosmosdb/pull/541) -- [Errors no longer written to output in the middle of writing a scrapbook command](https://github.com/Microsoft/vscode-cosmosdb/issues/516) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.0%22+is%3Aclosed+label%3Abug) - - -## 0.6.0 - 2018-04-09 - -### Added - -- Mongo - - mongo.shell.path setting no longer required if shell is in system path - - Allow mongo.shell.path to be specified in workspace settings as well as user settings - - No longer asking for an id for new documents - - Connected database is now persisted between sessions - - Improvements to scrapbook setup and error handling - -- Azure subscriptions - - New "filter" button on subscription nodes - - New "Open in Portal" menu item for subscriptions - -- Miscellaneous - - New "Report an Issue" button on error dialogs - -### Fixed - -- [Allow access to multi-tenant mongo server](https://github.com/Microsoft/vscode-cosmosdb/issues/473) -- [Can only run the first command in a Mongo Scrapbook on Windows](https://github.com/Microsoft/vscode-cosmosdb/issues/386) -- [Projections Not Working In Mongo Scrapbooks](https://github.com/Microsoft/vscode-cosmosdb/issues/214) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.6.0%22+is%3Aclosed+label%3Abug) - -## 0.5.1 - 2018-03-23 - -### Fixed -- [Bug fixed](https://github.com/Microsoft/vscode-cosmosdb/issues/372) -## 0.5.0 - 2018-03-05 - -### Fixed - -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.5.0%22+is%3Aclosed+label%3Abug) - -### Added - -- DocumentDB and Mongo - - Allow updating documents and collections re-opened from a previous VS Code session -- Mongo - - Delete databases - -## 0.4.0 - 2018-01-25 -### Added -- Attach to Cosmos DB emulator -- Run commands from the command palette - -### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.4.0%22+is%3Aclosed+label%3Abug) - -## 0.3.0 - 2017-12-15 -### Added -- Attach Cosmos DB accounts by connection string -- Graph: - - Customize the color and display text of vertices through VS Code [settings](README.md#graphSettings) - - By default display vertex IDs and labels and choose vertex color based on label - - Honor current VS Code theme - -### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.3.0%22+is%3Aclosed+label%3Abug) - -## 0.2.2 - 2017-12-04 -### Added -- View, edit, and persist a Mongo collection -- Edit and persist the result of a Mongo command - -## 0.2.1 - 2017-11-16 -### Fixed -- [Graph bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.1%22+is%3Aclosed+label%3Abug) - - Source to target arrows are backwards - - Side effects from executing a Gremlin query can occur twice - - Duplicate vertices can show up in graph viewer - - Query performance improved for large graphs - -## 0.2.0 - 2017-11-10 -### Added -- Graph: - - View/Create/Delete databases and graphs - - Click on a graph to visualize data - - Query graph using [Gremlin](https://docs.microsoft.com/azure/cosmos-db/gremlin-support) -- DocumentDB: - - View/Create/Delete databases, collections, and documents -- Mongo - - View documents in the explorer -- DocumentDB and Mongo: - - Click on a document to open in the editor - - Edit a document and persist changes to the cloud - - -### Removed -- View Mongo documents in 'result.json' by clicking on a collection in the explorer -- Edit and persist the result of a Mongo scrapbook command - -### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.0%22+is%3Aclosed+label%3Abug) - -## 0.1.1 - 2017-09-19 -### Changed -- Correctly set version to preview - -## 0.1.0 - 2017-09-19 -### Added -- Cosmos DB UI component (sash) -- Connect to local MongoDB -- Create Cosmos DB (with MongoDB adaptor) -- Connect to Cosmos DB via MongoDB adaptor -- Command to launch the `mongo` shell -- Rich MongoDB intellisense in scrapbooks diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index f9ba8cf65..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,9 +0,0 @@ -# Microsoft Open Source Code of Conduct - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). - -Resources: - -- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) -- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) -- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index f7b89984f..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,41 +0,0 @@ - - -## Security - -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). - -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. - -## Reporting Security Issues - -**Please do not report security vulnerabilities through public GitHub issues.** - -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). - -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). - -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). - -Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue - -This information will help us triage your report more quickly. - -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. - -## Preferred Languages - -We prefer all communications to be in English. - -## Policy - -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - - \ No newline at end of file diff --git a/SUPPORT.md b/SUPPORT.md deleted file mode 100644 index 06703d2d0..000000000 --- a/SUPPORT.md +++ /dev/null @@ -1,9 +0,0 @@ -# Support - -## How to file issues and get help - -This project uses GitHub Issues to track bugs and feature requests. Please see https://aka.ms/azCodeIssueReporting for our issue reporting guidelines. - -## Microsoft Support Policy - -Support for this project is limited to the resources listed above. diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e16bd2f53..000000000 --- a/package-lock.json +++ /dev/null @@ -1,21347 +0,0 @@ -{ - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "license": "SEE LICENSE IN LICENSE.md", - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "engines": { - "vscode": "^1.66.0" - } - }, - "node_modules/@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@azure/abort-controller/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "node_modules/@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-cosmosdb/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-subscriptions/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-auth/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-client/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-lro/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "dependencies": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-paging/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-tracing/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-util/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/cosmos/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/cosmos/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/logger/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "node_modules/@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - } - }, - "node_modules/@azure/ms-rest-js/node_modules/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, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "dependencies": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "dependencies": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - }, - "peerDependencies": { - "tslib": "*" - } - }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "node_modules/@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "dependencies": { - "@typescript-eslint/parser": "^4.28.5" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=4", - "eslint": ">=7", - "eslint-plugin-import": ">=2" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "dependencies": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "dependencies": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "bin": { - "vscode-sort-package-json": "scripts/sortPackageJson.mjs" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "dependencies": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - }, - "node_modules/@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "dependencies": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "node_modules/@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "dependencies": { - "@types/webpack": "*" - } - }, - "node_modules/@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "node_modules/@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "dependencies": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "node_modules/@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "dependencies": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - } - }, - "node_modules/@types/gulp/node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/gulp/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@types/gulp/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@types/gulp/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/gulp/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/@types/gulp/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/@types/gulp/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "node_modules/@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "dependencies": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "node_modules/@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "node_modules/@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "node_modules/@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/uglify-js/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "node_modules/@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "node_modules/@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "dependencies": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "node_modules/@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "node_modules/@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "dependencies": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/webpack/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "dependencies": { - "fast-memoize": "^2.3.2" - } - }, - "node_modules/@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "dependencies": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - }, - "engines": { - "vscode": "^1.60.0" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/@vscode/test-electron/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "engines": { - "node": ">= 0.6.15" - } - }, - "node_modules/adal-node/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "node_modules/antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true, - "bin": { - "antlr4ts": "antlr4ts" - } - }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "dependencies": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - }, - "engines": { - "node": ">=8.9.0" - }, - "peerDependencies": { - "webpack": "*" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "node_modules/copy-props/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "dependencies": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/copy-webpack-plugin/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/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, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true, - "engines": { - "node": ">0.4.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "dev": true - }, - "node_modules/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 - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/enquirer/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/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 - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-glob/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli/node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, - "engines": { - "node": ">=10.23.2" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "dependencies": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/indexable-array/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/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 - }, - "node_modules/log-symbols/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true, - "engines": { - "node": ">= 6.14.4" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "peerDependencies": { - "mocha": ">=2.2.5" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-junit-reporter/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha-junit-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - } - }, - "node_modules/mocha-multi-reporters/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/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 - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - }, - "peerDependenciesMeta": { - "aws4": { - "optional": true - }, - "bson-ext": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "mongodb-extjson": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "dependencies": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/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, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "dependencies": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dependencies": { - "split": "^1.0.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "dependencies": { - "parseley": "^0.7.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/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 - }, - "node_modules/slice-ansi/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-color/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/table/node_modules/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/tas-client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tmp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "dependencies": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "engines": { - "node": ">=6.11.5" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/ts-loader/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "out/vsce" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "dependencies": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - } - }, - "node_modules/vscode-json-languageservice/node_modules/vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "dependencies": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "engines": { - "vscode": "^1.41.0" - } - }, - "node_modules/vscode-languageclient/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "dependencies": { - "vscode-languageserver-protocol": "^3.15.3" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "dependencies": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "node_modules/vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "dependencies": { - "tas-client": "0.1.45" - }, - "engines": { - "vscode": "^1.19.1" - } - }, - "node_modules/vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-cli/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/webpack-cli/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, - "node_modules/yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "requires": { - "tslib": "^2.0.0" - }, - "dependencies": { - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - } - } - }, - "@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==" - }, - "@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "requires": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - }, - "dependencies": { - "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 - } - } - }, - "@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "requires": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "requires": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "requires": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^4.28.5" - } - }, - "@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "requires": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "dependencies": { - "@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "requires": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "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 - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - } - }, - "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } - } - } - }, - "@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "requires": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - } - } - }, - "@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "requires": {} - }, - "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - } - }, - "@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "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" - } - } - } - }, - "@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "requires": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, - "@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "requires": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - }, - "dependencies": { - "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" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "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" - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.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" - } - }, - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "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" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true - } - } - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "requires": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "requires": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - } - }, - "@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - } - }, - "@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "requires": { - "fast-memoize": "^2.3.2" - } - }, - "@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "requires": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - } - }, - "@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "dependencies": { - "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" - } - } - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "requires": {} - }, - "@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "requires": {} - }, - "adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - } - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "requires": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - } - } - }, - "copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "requires": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "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" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.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" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true - }, - "dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "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 - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "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==" - }, - "eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "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" - } - }, - "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" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "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 - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.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" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.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" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "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" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "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" - } - } - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "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" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "requires": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.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": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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" - } - } - } - }, - "loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "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.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^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" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.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 - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "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" - } - }, - "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 - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "requires": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "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 - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "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" - } - } - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "requires": { - "require-at": "^1.0.6" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "requires": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "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 - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "requires": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - } - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "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" - }, - "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" - } - }, - "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 - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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 - } - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "requires": { - "parseley": "^0.7.0" - } - }, - "semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=" - }, - "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "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 - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.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" - } - }, - "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 - }, - "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 - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "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" - } - } - } - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "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 - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "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" - } - } - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } - } - }, - "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - } - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "requires": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - }, - "dependencies": { - "vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - } - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "requires": { - "vscode-languageserver-protocol": "^3.15.3" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "requires": { - "tas-client": "0.1.45" - } - }, - "vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - } - } - }, - "webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - } - } - }, - "webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - } - }, - "webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "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" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index b710e8ca1..6cf8b5d51 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "displayName": "Azure Databases", "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", "engines": { - "vscode": "^1.66.0" + "vscode": "1.66.0" }, "galleryBanner": { "color": "#3c3c3c", @@ -1052,61 +1052,61 @@ "prepare": "husky install" }, "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", + "@azure/arm-resources": "4.0.0", + "@microsoft/eslint-config-azuretools": "0.1.0", + "@microsoft/vscode-azext-dev": "0.1.4", + "@types/copy-webpack-plugin": "6.4.0", + "@types/documentdb": "1.10.2", + "@types/fs-extra": "8.1.0", + "@types/gulp": "4.0.6", + "@types/mocha": "7.0.2", + "@types/mongodb": "3.3.2", + "@types/node": "14.0.0", + "@types/pg": "8.10.2", "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" + "@typescript-eslint/eslint-plugin": "4.31.1", + "@vscode/test-electron": "2.1.5", + "antlr4ts-cli": "0.4.0-alpha.4", + "copy-webpack-plugin": "6.4.0", + "eslint": "7.19.0", + "eslint-plugin-import": "2.22.1", + "glob": "7.1.6", + "gulp": "4.0.0", + "husky": "7.0.2", + "mocha": "10.2.0", + "mocha-junit-reporter": "1.18.0", + "mocha-multi-reporters": "1.1.7", + "ts-node": "7.0.1", + "typescript": "4.4.3", + "vsce": "1.87.0", + "webpack": "5.76.0", + "webpack-cli": "4.6.0", + "webpack-log": "3.0.2" }, "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" + "@azure/arm-cosmosdb": "15.0.0", + "@azure/arm-postgresql": "6.0.0", + "@azure/arm-postgresql-flexible": "5.0.0", + "@azure/cosmos": "3.6.3", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.0", + "antlr4ts": "0.4.1-alpha.0", + "bson": "1.1.3", + "fs-extra": "8.0.0", + "mongodb": "3.6.10", + "mongodb-extended-json": "1.10.0", + "open": "8.0.0", + "pg": "8.11.2", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.2", + "underscore": "1.12.1", + "vscode-json-languageservice": "3.0.8", + "vscode-languageclient": "6.1.3", + "vscode-languageserver": "6.1.1", + "vscode-languageserver-textdocument": "1.0.1", + "vscode-nls": "4.0.0", + "vscode-uri": "1.0.1" }, "extensionDependencies": [ "ms-vscode.azure-account", From 26df59f76fd0b0bb027551d8f0af1d869b79b1d6 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 08:05:28 +0200 Subject: [PATCH 04/33] squash! --- package.json | 92 ++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index 6cf8b5d51..02195bfc3 100644 --- a/package.json +++ b/package.json @@ -1052,61 +1052,61 @@ "prepare": "husky install" }, "devDependencies": { - "@azure/arm-resources": "4.0.0", - "@microsoft/eslint-config-azuretools": "0.1.0", - "@microsoft/vscode-azext-dev": "0.1.4", - "@types/copy-webpack-plugin": "6.4.0", - "@types/documentdb": "1.10.2", - "@types/fs-extra": "8.1.0", - "@types/gulp": "4.0.6", - "@types/mocha": "7.0.2", - "@types/mongodb": "3.3.2", - "@types/node": "14.0.0", - "@types/pg": "8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "4.31.1", - "@vscode/test-electron": "2.1.5", - "antlr4ts-cli": "0.4.0-alpha.4", - "copy-webpack-plugin": "6.4.0", - "eslint": "7.19.0", - "eslint-plugin-import": "2.22.1", - "glob": "7.1.6", - "gulp": "4.0.0", - "husky": "7.0.2", + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.1", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.11", + "@types/fs-extra": "11.0.3", + "@types/gulp": "4.0.16", + "@types/mocha": "10.0.3", + "@types/mongodb": "4.0.6", + "@types/node": "20.8.9", + "@types/pg": "8.10.7", + "@types/vscode": "1.83.1", + "@typescript-eslint/eslint-plugin": "6.9.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.52.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", "mocha": "10.2.0", - "mocha-junit-reporter": "1.18.0", - "mocha-multi-reporters": "1.1.7", - "ts-node": "7.0.1", - "typescript": "4.4.3", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", "vsce": "1.87.0", - "webpack": "5.76.0", - "webpack-cli": "4.6.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", "webpack-log": "3.0.2" }, "dependencies": { - "@azure/arm-cosmosdb": "15.0.0", - "@azure/arm-postgresql": "6.0.0", - "@azure/arm-postgresql-flexible": "5.0.0", - "@azure/cosmos": "3.6.3", + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.0", - "antlr4ts": "0.4.1-alpha.0", - "bson": "1.1.3", - "fs-extra": "8.0.0", - "mongodb": "3.6.10", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.2.0", "mongodb-extended-json": "1.10.0", - "open": "8.0.0", - "pg": "8.11.2", + "open": "9.1.0", + "pg": "8.11.3", "pg-connection-string": "2.6.2", "pg-structure": "7.15.0", - "semver": "7.5.2", - "underscore": "1.12.1", - "vscode-json-languageservice": "3.0.8", - "vscode-languageclient": "6.1.3", - "vscode-languageserver": "6.1.1", - "vscode-languageserver-textdocument": "1.0.1", - "vscode-nls": "4.0.0", - "vscode-uri": "1.0.1" + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" }, "extensionDependencies": [ "ms-vscode.azure-account", From d776dd874e6daba480c91886532949e0e48b65e5 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 09:47:48 +0200 Subject: [PATCH 05/33] squash! --- package.json | 2226 +++++++++++++++++++++++++------------------------- 1 file changed, 1119 insertions(+), 1107 deletions(-) diff --git a/package.json b/package.json index 02195bfc3..98ad1d912 100644 --- a/package.json +++ b/package.json @@ -1,1115 +1,1127 @@ { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", - "publisher": "ms-azuretools", - "displayName": "Azure Databases", - "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "engines": { - "vscode": "1.66.0" - }, - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "icon": "resources/databases.png", - "categories": [ - "Azure" - ], - "keywords": [ - "Cosmos DB", - "DocumentDB", - "Graph", - "Gremlin", - "MongoDB", - "PostgreSQL" - ], - "preview": true, - "homepage": "https://github.com/microsoft/vscode-cosmosdb/blob/main/README.md", - "bugs": { - "url": "https://github.com/microsoft/vscode-cosmosdb/issues" - }, - "license": "SEE LICENSE IN LICENSE.md", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-cosmosdb" - }, - "main": "./main", - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], - "contributes": { - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - }, - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } + "name": "vscode-cosmosdb", + "version": "0.0.1", + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", + "publisher": "ms-azuretools", + "displayName": "Azure Databases", + "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", + "engines": { + "vscode": "1.66.0" + }, + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "icon": "resources/databases.png", + "categories": [ + "Azure" + ], + "keywords": [ + "Cosmos DB", + "DocumentDB", + "Graph", + "Gremlin", + "MongoDB", + "PostgreSQL" + ], + "preview": true, + "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", + "bugs": { + "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" + }, + "main": "./main", + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "contributes": { + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" + }, + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } ], - "commands": [ - { - "category": "Azure Databases", - "command": "azureDatabases.createServer", - "title": "Create Server...", - "icon": "$(add)" - }, - { - "category": "Cosmos DB", - "command": "azureDatabases.detachDatabaseAccount", - "title": "Detach" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.loadMore", - "title": "Load More" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.refresh", - "title": "Refresh", - "icon": "$(refresh)" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.reportIssue", - "title": "Report Issue..." - }, - { - "category": "Azure Databases", - "command": "azureDatabases.update", - "title": "Update to Cloud", - "icon": "$(cloud-upload)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachDatabaseAccount", - "title": "Attach Database Account...", - "icon": "$(plug)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachEmulator", - "title": "Attach Emulator..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.connectMongoDB", - "title": "Connect to Database..." - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBCollection", - "title": "Create Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDatabase", - "title": "Create Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDocument", - "title": "Create Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBStoredProcedure", - "title": "Create Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraph", - "title": "Create Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraphDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoCollection", - "title": "Create Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDocument", - "title": "Create Document" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.deleteAccount", - "title": "Delete Account..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBCollection", - "title": "Delete Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDatabase", - "title": "Delete Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDocument", - "title": "Delete Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraph", - "title": "Delete Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraphDatabase", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoCollection", - "title": "Delete Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDB", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDocument", - "title": "Delete Document..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeAllMongoCommands", - "title": "Execute All MongoDB Commands" - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeMongoCommand", - "title": "Execute MongoDB Command" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.importDocument", - "title": "Import Document into a Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.launchMongoShell", - "title": "Launch Shell" - }, - { - "category": "MongoDB", - "command": "cosmosDB.newMongoScrapbook", - "title": "New Mongo Scrapbook", - "icon": "$(new-file)" - }, - { - "category": "MongoDB", - "command": "cosmosDB.openCollection", - "title": "Open Collection" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openDocument", - "title": "Open Document" - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.openGraphExplorer", - "title": "Open Graph Explorer" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.configureFirewall", - "title": "Configure Firewall" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.connectDatabase", - "title": "Connect to Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createDatabase", - "title": "Create Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createFunctionQuery", - "title": "Create Function Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createStoredProcedureQuery", - "title": "Create Stored Procedure Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteDatabase", - "title": "Delete Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteFunction", - "title": "Delete Function..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteServer", - "title": "Delete Server..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteTable", - "title": "Delete Table..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.enterCredentials", - "title": "Enter Server Credentials" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.executeQuery", - "title": "Execute Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openFunction", - "title": "Open Function" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.showPasswordlessWiki", - "title": "Learn more about authenticating with Azure Active Directory", - "icon": "$(warning)" - } + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." + } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] + } + }, + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" ], - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } + "extensions": [ + ".mongo" ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId==postgres" - } - ], - "editor/title": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "azureDatabases.createServer", - "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", - "group": "1@1" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteServer", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@1" - }, - { - "command": "postgreSQL.showPasswordlessWiki", - "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", - "group": "inline" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@1" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@2" - }, - { - "command": "cosmosDB.connectMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "2@1" - }, - { - "command": "cosmosDB.deleteMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@4" - }, - { - "command": "cosmosDB.deleteMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraphDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteTable", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteFunction", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", - "group": "1@2" - }, - { - "command": "cosmosDB.attachDatabaseAccount", - "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "1@1" - }, - { - "command": "cosmosDB.attachEmulator", - "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", - "group": "1@2" - }, - { - "command": "cosmosDB.openCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "2@1" - }, - { - "command": "postgreSQL.copyConnectionString", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "2@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", - "group": "1@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "2@1" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@3" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@1" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createFunctionQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "1@1" - }, - { - "command": "postgreSQL.createStoredProcedureQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "1@1" - } - ], - "explorer/context": [ - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId == json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId == postgres" - } - ], - "commandPalette": [ - { - "command": "azureDatabases.loadMore", - "when": "never" - }, - { - "command": "azureDatabases.refresh", - "when": "never" - }, - { - "command": "azureDatabases.update", - "when": "never" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "editorLangId == 'mongo'" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "editorLangId == 'mongo'" - }, - { - "command": "postgreSQL.executeQuery", - "when": "editorLangId == 'postgres'" - } - ] - }, - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" - } + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" - } - } + "extensions": [ + ".psql" + ] + } + ], + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "commands": [ + { + "category": "Azure Databases", + "command": "azureDatabases.createServer", + "title": "Create Server...", + "icon": "$(add)" + }, + { + "category": "Cosmos DB", + "command": "azureDatabases.detachDatabaseAccount", + "title": "Detach" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.loadMore", + "title": "Load More" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.reportIssue", + "title": "Report Issue..." + }, + { + "category": "Azure Databases", + "command": "azureDatabases.update", + "title": "Update to Cloud", + "icon": "$(cloud-upload)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachDatabaseAccount", + "title": "Attach Database Account...", + "icon": "$(plug)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachEmulator", + "title": "Attach Emulator..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.connectMongoDB", + "title": "Connect to Database..." + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBCollection", + "title": "Create Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDatabase", + "title": "Create Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDocument", + "title": "Create Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBStoredProcedure", + "title": "Create Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraph", + "title": "Create Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraphDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoCollection", + "title": "Create Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDocument", + "title": "Create Document" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.deleteAccount", + "title": "Delete Account..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBCollection", + "title": "Delete Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDatabase", + "title": "Delete Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDocument", + "title": "Delete Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraph", + "title": "Delete Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraphDatabase", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoCollection", + "title": "Delete Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDB", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDocument", + "title": "Delete Document..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeAllMongoCommands", + "title": "Execute All MongoDB Commands" + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeMongoCommand", + "title": "Execute MongoDB Command" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.importDocument", + "title": "Import Document into a Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.launchMongoShell", + "title": "Launch Shell" + }, + { + "category": "MongoDB", + "command": "cosmosDB.newMongoScrapbook", + "title": "New Mongo Scrapbook", + "icon": "$(new-file)" + }, + { + "category": "MongoDB", + "command": "cosmosDB.openCollection", + "title": "Open Collection" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openDocument", + "title": "Open Document" + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.openGraphExplorer", + "title": "Open Graph Explorer" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.configureFirewall", + "title": "Configure Firewall" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.connectDatabase", + "title": "Connect to Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createDatabase", + "title": "Create Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createFunctionQuery", + "title": "Create Function Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createStoredProcedureQuery", + "title": "Create Stored Procedure Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteDatabase", + "title": "Delete Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteFunction", + "title": "Delete Function..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteServer", + "title": "Delete Server..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteTable", + "title": "Delete Table..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.enterCredentials", + "title": "Enter Server Credentials" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.executeQuery", + "title": "Execute Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openFunction", + "title": "Open Function" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.showPasswordlessWiki", + "title": "Learn more about authenticating with Azure Active Directory", + "icon": "$(warning)" + } + ], + "submenus": [ + { + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId==postgres" + } + ], + "editor/title": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "azureDatabases.createServer", + "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", + "group": "1@1" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteServer", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@1" + }, + { + "command": "postgreSQL.showPasswordlessWiki", + "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", + "group": "inline" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@1" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@2" + }, + { + "command": "cosmosDB.connectMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "2@1" + }, + { + "command": "cosmosDB.deleteMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@4" + }, + { + "command": "cosmosDB.deleteMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraphDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteTable", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteFunction", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", + "group": "1@2" + }, + { + "command": "cosmosDB.attachDatabaseAccount", + "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "1@1" + }, + { + "command": "cosmosDB.attachEmulator", + "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", + "group": "1@2" + }, + { + "command": "cosmosDB.openCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "2@1" + }, + { + "command": "postgreSQL.copyConnectionString", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "2@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", + "group": "1@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "2@1" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@3" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@1" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createFunctionQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "1@1" + }, + { + "command": "postgreSQL.createStoredProcedureQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "1@1" + } + ], + "explorer/context": [ + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId == json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId == postgres" + } + ], + "commandPalette": [ + { + "command": "azureDatabases.loadMore", + "when": "never" + }, + { + "command": "azureDatabases.refresh", + "when": "never" + }, + { + "command": "azureDatabases.update", + "when": "never" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "editorLangId == 'mongo'" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "editorLangId == 'mongo'" + }, + { + "command": "postgreSQL.executeQuery", + "when": "editorLangId == 'postgres'" + } + ] }, - "scripts": { - "vscode:prepublish": "npm run webpack-prod", - "build": "tsc", - "cleanReadme": "gulp cleanReadme", - "clean": "git clean -dfx", - "compile": "tsc -watch", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", - "all": "npm i && npm run lint && npm test", - "prepare": "husky install" - }, - "devDependencies": { - "@azure/arm-resources": "5.2.0", - "@microsoft/eslint-config-azuretools": "0.2.1", - "@microsoft/vscode-azext-dev": "2.0.2", - "@types/copy-webpack-plugin": "8.0.1", - "@types/documentdb": "1.10.11", - "@types/fs-extra": "11.0.3", - "@types/gulp": "4.0.16", - "@types/mocha": "10.0.3", - "@types/mongodb": "4.0.6", - "@types/node": "20.8.9", - "@types/pg": "8.10.7", - "@types/vscode": "1.83.1", - "@typescript-eslint/eslint-plugin": "6.9.0", - "@vscode/test-electron": "2.3.6", - "antlr4ts-cli": "0.5.0-alpha.4", - "copy-webpack-plugin": "11.0.0", - "eslint": "8.52.0", - "eslint-plugin-import": "2.29.0", - "glob": "10.3.10", - "gulp": "4.0.2", - "husky": "8.0.3", - "mocha": "10.2.0", - "mocha-junit-reporter": "2.2.1", - "mocha-multi-reporters": "1.5.1", - "ts-node": "10.9.1", - "typescript": "5.2.2", - "vsce": "1.87.0", - "webpack": "5.89.0", - "webpack-cli": "5.1.4", - "webpack-log": "3.0.2" - }, - "dependencies": { - "@azure/arm-cosmosdb": "15.5.0", - "@azure/arm-postgresql": "6.1.0", - "@azure/arm-postgresql-flexible": "7.1.0", - "@azure/cosmos": "4.0.0", - "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.3", - "antlr4ts": "0.5.0-alpha.4", - "bson": "6.2.0", - "fs-extra": "11.1.1", - "mongodb": "6.2.0", - "mongodb-extended-json": "1.10.0", - "open": "9.1.0", - "pg": "8.11.3", - "pg-connection-string": "2.6.2", - "pg-structure": "7.15.0", - "semver": "7.5.4", - "underscore": "1.13.6", - "vscode-json-languageservice": "5.3.7", - "vscode-languageclient": "9.0.1", - "vscode-languageserver": "9.0.1", - "vscode-languageserver-textdocument": "1.0.11", - "vscode-nls": "5.2.0", - "vscode-uri": "3.0.8" - }, - "extensionDependencies": [ - "ms-vscode.azure-account", - "ms-azuretools.vscode-azureresourcegroups" - ] + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null + }, + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] + }, + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 + }, + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" + }, + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" + }, + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + } + }, + "scripts": { + "vscode:prepublish": "npm run webpack-prod", + "build": "tsc", + "cleanReadme": "gulp cleanReadme", + "clean": "git clean -dfx", + "compile": "tsc -watch", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", + "all": "npm i && npm run lint && npm test", + "prepare": "husky install", + "prepublishOnly": "TypeScriptESBuild Source/**/*.ts" + }, + "devDependencies": { + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.1", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.11", + "@types/fs-extra": "11.0.3", + "@types/gulp": "4.0.16", + "@types/mocha": "10.0.3", + "@types/mongodb": "4.0.6", + "@types/node": "20.8.9", + "@types/pg": "8.10.7", + "@types/vscode": "1.83.1", + "@typescript-eslint/eslint-plugin": "6.9.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.52.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2", + "typescript-esbuild": "0.3.1" + }, + "dependencies": { + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.2.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" + }, + "extensionDependencies": [ + "ms-vscode.azure-account", + "ms-azuretools.vscode-azureresourcegroups" + ], + "type": "module", + "private": "false", + "publishConfig": { + "access": "public" + }, + "author": { + "name": "Nikola Hristov", + "email": "nikola@nikolahristov.tech", + "url": "https://nikolahristov.tech" + } } From e3cd7941ac96c4616eca55d26f3b70d98c4de0ee Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 11:38:18 +0200 Subject: [PATCH 06/33] squash! --- .husky/pre-commit | 4 - package.json | 652 +++++++++++++++++++++++----------------------- 2 files changed, 326 insertions(+), 330 deletions(-) delete mode 100755 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 901b4c3f8..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx vscode-sort-package-json diff --git a/package.json b/package.json index 98ad1d912..69407e037 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,9 @@ { "name": "vscode-cosmosdb", - "version": "0.0.1", - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", - "publisher": "ms-azuretools", "displayName": "Azure Databases", + "version": "0.0.1", + "private": "false", "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "engines": { - "vscode": "1.66.0" - }, - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "icon": "resources/databases.png", "categories": [ "Azure" ], @@ -24,146 +15,45 @@ "MongoDB", "PostgreSQL" ], - "preview": true, "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", "bugs": { "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" }, - "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" }, + "license": "MIT", + "author": { + "name": "Nikola Hristov", + "email": "nikola@nikolahristov.tech", + "url": "https://nikolahristov.tech" + }, + "publisher": "playform", + "type": "module", "main": "./main", - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], + "scripts": { + "all": "npm i && npm run lint && npm test", + "build": "tsc", + "clean": "git clean -dfx", + "cleanReadme": "gulp cleanReadme", + "compile": "tsc -watch", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "prepare": "husky install", + "prepublishOnly": "TypeScriptESBuild Source/**/*.ts", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "vscode:prepublish": "npm run webpack-prod", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats" + }, "contributes": { - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - }, - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } - ], "commands": [ { "category": "Azure Databases", @@ -442,55 +332,174 @@ "icon": "$(warning)" } ], - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } - ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + }, + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" + ], + "extensions": [ + ".mongo" + ], + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" + ], + "extensions": [ + ".psql" + ] + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" + } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" }, { "command": "postgreSQL.connectDatabase", @@ -938,119 +947,132 @@ } ] }, - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, + "submenus": [ { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" } ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } + ], + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] } } }, - "scripts": { - "vscode:prepublish": "npm run webpack-prod", - "build": "tsc", - "cleanReadme": "gulp cleanReadme", - "clean": "git clean -dfx", - "compile": "tsc -watch", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", - "all": "npm i && npm run lint && npm test", - "prepare": "husky install", - "prepublishOnly": "TypeScriptESBuild Source/**/*.ts" + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "dependencies": { + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.2.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" }, "devDependencies": { "@azure/arm-resources": "5.2.0", @@ -1079,49 +1101,27 @@ "mocha-multi-reporters": "1.5.1", "ts-node": "10.9.1", "typescript": "5.2.2", + "typescript-esbuild": "0.3.1", "vsce": "1.87.0", "webpack": "5.89.0", "webpack-cli": "5.1.4", - "webpack-log": "3.0.2", - "typescript-esbuild": "0.3.1" - }, - "dependencies": { - "@azure/arm-cosmosdb": "15.5.0", - "@azure/arm-postgresql": "6.1.0", - "@azure/arm-postgresql-flexible": "7.1.0", - "@azure/cosmos": "4.0.0", - "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.3", - "antlr4ts": "0.5.0-alpha.4", - "bson": "6.2.0", - "fs-extra": "11.1.1", - "mongodb": "6.2.0", - "mongodb-extended-json": "1.10.0", - "open": "9.1.0", - "pg": "8.11.3", - "pg-connection-string": "2.6.2", - "pg-structure": "7.15.0", - "semver": "7.5.4", - "underscore": "1.13.6", - "vscode-json-languageservice": "5.3.7", - "vscode-languageclient": "9.0.1", - "vscode-languageserver": "9.0.1", - "vscode-languageserver-textdocument": "1.0.11", - "vscode-nls": "5.2.0", - "vscode-uri": "3.0.8" + "webpack-log": "3.0.2" }, "extensionDependencies": [ - "ms-vscode.azure-account", - "ms-azuretools.vscode-azureresourcegroups" + "ms-azuretools.vscode-azureresourcegroups", + "ms-vscode.azure-account" ], - "type": "module", - "private": "false", + "engines": { + "vscode": "1.66.0" + }, "publishConfig": { "access": "public" }, - "author": { - "name": "Nikola Hristov", - "email": "nikola@nikolahristov.tech", - "url": "https://nikolahristov.tech" - } + "icon": "resources/databases.png", + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "preview": true, + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255" } From 4cfa077a67556ed2caf62a6b15ad75b3603ef244 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 29 Oct 2023 21:39:38 +0200 Subject: [PATCH 07/33] squash! --- {src => Source}/AzureDBExperiences.ts | 0 {src => Source}/DatabasesFileSystem.ts | 0 {src => Source}/ParsedConnectionString.ts | 0 {src => Source}/azureAccountUtils.ts | 0 .../api/DatabaseAccountTreeItemInternal.ts | 0 .../commands/api/DatabaseTreeItemInternal.ts | 0 {src => Source}/commands/api/apiCache.ts | 0 {src => Source}/commands/api/findTreeItem.ts | 0 {src => Source}/commands/api/pickTreeItem.ts | 0 {src => Source}/commands/api/revealTreeItem.ts | 0 .../DatabaseAccountDeleteStep.ts | 0 .../IDeleteWizardContext.ts | 0 .../deleteCosmosDBAccount.ts | 0 .../deleteDatabaseAccount.ts | 0 {src => Source}/commands/importDocuments.ts | 0 {src => Source}/constants.ts | 0 {src => Source}/docdb/docDBConnectionStrings.ts | 0 {src => Source}/docdb/getCosmosClient.ts | 0 {src => Source}/docdb/registerDocDBCommands.ts | 0 .../docdb/tree/DocDBAccountTreeItem.ts | 0 .../docdb/tree/DocDBAccountTreeItemBase.ts | 0 .../docdb/tree/DocDBCollectionTreeItem.ts | 0 .../docdb/tree/DocDBDatabaseTreeItem.ts | 0 .../docdb/tree/DocDBDatabaseTreeItemBase.ts | 0 .../docdb/tree/DocDBDocumentTreeItem.ts | 0 .../docdb/tree/DocDBDocumentsTreeItem.ts | 0 .../docdb/tree/DocDBStoredProcedureTreeItem.ts | 0 .../docdb/tree/DocDBStoredProceduresTreeItem.ts | 0 {src => Source}/docdb/tree/DocDBTreeItemBase.ts | 0 {src => Source}/docdb/tree/DocDBUtils.ts | 0 {src => Source}/docdb/tree/IDocDBTreeRoot.ts | 0 {src => Source}/extension.ts | 0 {src => Source}/extensionVariables.ts | 0 {src => Source}/getExtensionApi.ts | 0 {src => Source}/graph/gremlinEndpoints.ts | 0 {src => Source}/graph/registerGraphCommands.ts | 0 .../graph/tree/GraphAccountTreeItem.ts | 0 .../graph/tree/GraphCollectionTreeItem.ts | 0 .../graph/tree/GraphDatabaseTreeItem.ts | 0 {src => Source}/graph/tree/GraphTreeItem.ts | 0 {src => Source}/mongo/MongoCommand.ts | 0 {src => Source}/mongo/MongoScrapbook.ts | 0 {src => Source}/mongo/MongoShell.ts | 0 {src => Source}/mongo/connectToMongoClient.ts | 0 {src => Source}/mongo/errorListeners.ts | 0 {src => Source}/mongo/grammar/mongo.tokens | 0 {src => Source}/mongo/grammar/mongoLexer.tokens | 0 {src => Source}/mongo/grammar/mongoLexer.ts | 0 {src => Source}/mongo/grammar/mongoListener.ts | 0 {src => Source}/mongo/grammar/mongoParser.ts | 0 {src => Source}/mongo/grammar/mongoVisitor.ts | 0 {src => Source}/mongo/grammar/visitors.ts | 0 {src => Source}/mongo/languageClient.ts | 0 {src => Source}/mongo/languageServer.ts | 0 {src => Source}/mongo/mongoConnectionStrings.ts | 0 {src => Source}/mongo/registerMongoCommands.ts | 0 .../mongo/services/IConnectionParams.ts | 0 .../mongo/services/MongoCodeLensProvider.ts | 0 .../mongo/services/completionItemProvider.ts | 0 .../mongo/services/languageService.ts | 0 {src => Source}/mongo/services/mongoScript.ts | 0 {src => Source}/mongo/services/schemaService.ts | 0 {src => Source}/mongo/setConnectedNode.ts | 0 {src => Source}/mongo/tree/IMongoTreeRoot.ts | 0 .../mongo/tree/MongoAccountTreeItem.ts | 0 .../mongo/tree/MongoCollectionTreeItem.ts | 0 .../mongo/tree/MongoDatabaseTreeItem.ts | 0 .../mongo/tree/MongoDocumentTreeItem.ts | 0 .../postgres/abstract/AbstractPostgresClient.ts | 0 {src => Source}/postgres/abstract/models.ts | 0 .../postgres/commands/checkAuthentication.ts | 0 .../commands/configurePostgresFirewall.ts | 0 .../postgres/commands/connectPostgresDatabase.ts | 0 .../postgres/commands/copyConnectionString.ts | 0 .../postgres/commands/createPostgresDatabase.ts | 0 .../IPostgresQueryWizardContext.ts | 0 .../IPostgresFunctionQueryWizardContext.ts | 0 .../function/createPostgresFunctionQuery.ts | 0 .../function/steps/FunctionQueryCreateStep.ts | 0 .../steps/FunctionQueryCustomReturnTypeStep.ts | 0 .../function/steps/FunctionQueryNameStep.ts | 0 .../steps/FunctionQueryReturnTypeStep.ts | 0 .../runPostgresQueryWizard.ts | 0 .../createPostgresStoredProcedureQuery.ts | 0 .../steps/StoredProcedureQueryCreateStep.ts | 0 .../steps/StoredProcedureQueryNameStep.ts | 0 .../createPostgresQuery/validateIdentifier.ts | 0 .../IPostgresServerWizardContext.ts | 0 .../steps/PostgresServerConfirmPWStep.ts | 0 .../steps/PostgresServerCreateStep.ts | 0 .../steps/PostgresServerCredPWStep.ts | 0 .../steps/PostgresServerCredUserStep.ts | 0 .../steps/PostgresServerNameStep.ts | 0 .../steps/PostgresServerSetCredentialsStep.ts | 0 .../steps/PostgresServerSkuStep.ts | 0 .../postgres/commands/deletePostgresDatabase.ts | 0 .../postgres/commands/deletePostgresFunction.ts | 0 .../postgres/commands/deletePostgresServer.ts | 0 .../commands/deletePostgresStoredProcedure.ts | 0 .../postgres/commands/deletePostgresTable.ts | 0 .../commands/enterPostgresCredentials.ts | 0 .../commands/executePostgresQueryInDocument.ts | 0 .../postgres/commands/openPostgresFunction.ts | 0 .../commands/openPostgresStoredProcedure.ts | 0 .../commands/registerPostgresCommands.ts | 0 .../postgres/commands/setPostgresCredentials.ts | 0 {src => Source}/postgres/getClientConfig.ts | 0 .../postgres/getPostgresProcedureQueryRows.ts | 0 {src => Source}/postgres/getTables.ts | 0 .../postgres/postgresConnectionStrings.ts | 0 {src => Source}/postgres/postgresConstants.ts | 0 {src => Source}/postgres/runPostgresQuery.ts | 0 .../services/PostgresCodeLensProvider.ts | 0 {src => Source}/postgres/showPostgresQuery.ts | 0 .../postgres/tree/ClientConfigFactory.ts | 0 .../postgres/tree/PostgresColumnTreeItem.ts | 0 .../postgres/tree/PostgresDatabaseTreeItem.ts | 0 .../postgres/tree/PostgresFunctionTreeItem.ts | 0 .../postgres/tree/PostgresFunctionsTreeItem.ts | 0 .../tree/PostgresResourcesTreeItemBase.ts | 0 .../postgres/tree/PostgresServerTreeItem.ts | 0 .../tree/PostgresStoredProcedureTreeItem.ts | 0 .../tree/PostgresStoredProceduresTreeItem.ts | 0 .../postgres/tree/PostgresTableTreeItem.ts | 0 .../postgres/tree/PostgresTablesTreeItem.ts | 0 {src => Source}/resolver/AppResolver.ts | 0 .../resolver/DatabaseWorkspaceProvider.ts | 0 .../resolver/ResolvedDatabaseAccountResource.ts | 0 .../resolver/ResolvedDocDBAccountResource.ts | 0 .../resolver/ResolvedMongoAccountResource.ts | 0 .../resolver/ResolvedPostgresServerResource.ts | 0 .../table/tree/TableAccountTreeItem.ts | 0 {src => Source}/tree/AttachedAccountsTreeItem.ts | 0 .../tree/AzureAccountTreeItemWithAttached.ts | 0 {src => Source}/tree/AzureDBAPIStep.ts | 0 .../CosmosDBAccountCapacityStep.ts | 0 .../CosmosDBAccountCreateStep.ts | 0 .../CosmosDBAccountNameStep.ts | 0 .../ICosmosDBWizardContext.ts | 0 {src => Source}/tree/IAzureDBWizardContext.ts | 0 {src => Source}/tree/SubscriptionTreeItem.ts | 0 {src => Source}/utils/InteractiveChildProcess.ts | 0 {src => Source}/utils/activityUtils.ts | 0 {src => Source}/utils/array.ts | 0 {src => Source}/utils/azureClients.ts | 0 {src => Source}/utils/azureUtils.ts | 0 {src => Source}/utils/cp.ts | 0 {src => Source}/utils/getIp.ts | 0 {src => Source}/utils/getSecretStorageKey.ts | 16 ++++++++-------- {src => Source}/utils/improveError.ts | 0 {src => Source}/utils/localize.ts | 0 {src => Source}/utils/nonNull.ts | 0 {src => Source}/utils/openUrl.ts | 0 {src => Source}/utils/randomUtils.ts | 0 {src => Source}/utils/settingUtils.ts | 0 {src => Source}/utils/timeout.ts | 0 {src => Source}/utils/vscodeUtils.ts | 0 {src => Source}/utils/workspacUtils.ts | 0 {src => Source}/utils/wrapError.ts | 0 {src => Source}/vscode-cosmosdb.api.d.ts | 0 {src => Source}/vscode-cosmosdbgraph.api.d.ts | 0 161 files changed, 8 insertions(+), 8 deletions(-) rename {src => Source}/AzureDBExperiences.ts (100%) rename {src => Source}/DatabasesFileSystem.ts (100%) rename {src => Source}/ParsedConnectionString.ts (100%) rename {src => Source}/azureAccountUtils.ts (100%) rename {src => Source}/commands/api/DatabaseAccountTreeItemInternal.ts (100%) rename {src => Source}/commands/api/DatabaseTreeItemInternal.ts (100%) rename {src => Source}/commands/api/apiCache.ts (100%) rename {src => Source}/commands/api/findTreeItem.ts (100%) rename {src => Source}/commands/api/pickTreeItem.ts (100%) rename {src => Source}/commands/api/revealTreeItem.ts (100%) rename {src => Source}/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts (100%) rename {src => Source}/commands/deleteDatabaseAccount/IDeleteWizardContext.ts (100%) rename {src => Source}/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts (100%) rename {src => Source}/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts (100%) rename {src => Source}/commands/importDocuments.ts (100%) rename {src => Source}/constants.ts (100%) rename {src => Source}/docdb/docDBConnectionStrings.ts (100%) rename {src => Source}/docdb/getCosmosClient.ts (100%) rename {src => Source}/docdb/registerDocDBCommands.ts (100%) rename {src => Source}/docdb/tree/DocDBAccountTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBAccountTreeItemBase.ts (100%) rename {src => Source}/docdb/tree/DocDBCollectionTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBDatabaseTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBDatabaseTreeItemBase.ts (100%) rename {src => Source}/docdb/tree/DocDBDocumentTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBDocumentsTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBStoredProcedureTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBStoredProceduresTreeItem.ts (100%) rename {src => Source}/docdb/tree/DocDBTreeItemBase.ts (100%) rename {src => Source}/docdb/tree/DocDBUtils.ts (100%) rename {src => Source}/docdb/tree/IDocDBTreeRoot.ts (100%) rename {src => Source}/extension.ts (100%) rename {src => Source}/extensionVariables.ts (100%) rename {src => Source}/getExtensionApi.ts (100%) rename {src => Source}/graph/gremlinEndpoints.ts (100%) rename {src => Source}/graph/registerGraphCommands.ts (100%) rename {src => Source}/graph/tree/GraphAccountTreeItem.ts (100%) rename {src => Source}/graph/tree/GraphCollectionTreeItem.ts (100%) rename {src => Source}/graph/tree/GraphDatabaseTreeItem.ts (100%) rename {src => Source}/graph/tree/GraphTreeItem.ts (100%) rename {src => Source}/mongo/MongoCommand.ts (100%) rename {src => Source}/mongo/MongoScrapbook.ts (100%) rename {src => Source}/mongo/MongoShell.ts (100%) rename {src => Source}/mongo/connectToMongoClient.ts (100%) rename {src => Source}/mongo/errorListeners.ts (100%) rename {src => Source}/mongo/grammar/mongo.tokens (100%) rename {src => Source}/mongo/grammar/mongoLexer.tokens (100%) rename {src => Source}/mongo/grammar/mongoLexer.ts (100%) rename {src => Source}/mongo/grammar/mongoListener.ts (100%) rename {src => Source}/mongo/grammar/mongoParser.ts (100%) rename {src => Source}/mongo/grammar/mongoVisitor.ts (100%) rename {src => Source}/mongo/grammar/visitors.ts (100%) rename {src => Source}/mongo/languageClient.ts (100%) rename {src => Source}/mongo/languageServer.ts (100%) rename {src => Source}/mongo/mongoConnectionStrings.ts (100%) rename {src => Source}/mongo/registerMongoCommands.ts (100%) rename {src => Source}/mongo/services/IConnectionParams.ts (100%) rename {src => Source}/mongo/services/MongoCodeLensProvider.ts (100%) rename {src => Source}/mongo/services/completionItemProvider.ts (100%) rename {src => Source}/mongo/services/languageService.ts (100%) rename {src => Source}/mongo/services/mongoScript.ts (100%) rename {src => Source}/mongo/services/schemaService.ts (100%) rename {src => Source}/mongo/setConnectedNode.ts (100%) rename {src => Source}/mongo/tree/IMongoTreeRoot.ts (100%) rename {src => Source}/mongo/tree/MongoAccountTreeItem.ts (100%) rename {src => Source}/mongo/tree/MongoCollectionTreeItem.ts (100%) rename {src => Source}/mongo/tree/MongoDatabaseTreeItem.ts (100%) rename {src => Source}/mongo/tree/MongoDocumentTreeItem.ts (100%) rename {src => Source}/postgres/abstract/AbstractPostgresClient.ts (100%) rename {src => Source}/postgres/abstract/models.ts (100%) rename {src => Source}/postgres/commands/checkAuthentication.ts (100%) rename {src => Source}/postgres/commands/configurePostgresFirewall.ts (100%) rename {src => Source}/postgres/commands/connectPostgresDatabase.ts (100%) rename {src => Source}/postgres/commands/copyConnectionString.ts (100%) rename {src => Source}/postgres/commands/createPostgresDatabase.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresQuery/validateIdentifier.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts (100%) rename {src => Source}/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts (100%) rename {src => Source}/postgres/commands/deletePostgresDatabase.ts (100%) rename {src => Source}/postgres/commands/deletePostgresFunction.ts (100%) rename {src => Source}/postgres/commands/deletePostgresServer.ts (100%) rename {src => Source}/postgres/commands/deletePostgresStoredProcedure.ts (100%) rename {src => Source}/postgres/commands/deletePostgresTable.ts (100%) rename {src => Source}/postgres/commands/enterPostgresCredentials.ts (100%) rename {src => Source}/postgres/commands/executePostgresQueryInDocument.ts (100%) rename {src => Source}/postgres/commands/openPostgresFunction.ts (100%) rename {src => Source}/postgres/commands/openPostgresStoredProcedure.ts (100%) rename {src => Source}/postgres/commands/registerPostgresCommands.ts (100%) rename {src => Source}/postgres/commands/setPostgresCredentials.ts (100%) rename {src => Source}/postgres/getClientConfig.ts (100%) rename {src => Source}/postgres/getPostgresProcedureQueryRows.ts (100%) rename {src => Source}/postgres/getTables.ts (100%) rename {src => Source}/postgres/postgresConnectionStrings.ts (100%) rename {src => Source}/postgres/postgresConstants.ts (100%) rename {src => Source}/postgres/runPostgresQuery.ts (100%) rename {src => Source}/postgres/services/PostgresCodeLensProvider.ts (100%) rename {src => Source}/postgres/showPostgresQuery.ts (100%) rename {src => Source}/postgres/tree/ClientConfigFactory.ts (100%) rename {src => Source}/postgres/tree/PostgresColumnTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresDatabaseTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresFunctionTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresFunctionsTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresResourcesTreeItemBase.ts (100%) rename {src => Source}/postgres/tree/PostgresServerTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresStoredProcedureTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresStoredProceduresTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresTableTreeItem.ts (100%) rename {src => Source}/postgres/tree/PostgresTablesTreeItem.ts (100%) rename {src => Source}/resolver/AppResolver.ts (100%) rename {src => Source}/resolver/DatabaseWorkspaceProvider.ts (100%) rename {src => Source}/resolver/ResolvedDatabaseAccountResource.ts (100%) rename {src => Source}/resolver/ResolvedDocDBAccountResource.ts (100%) rename {src => Source}/resolver/ResolvedMongoAccountResource.ts (100%) rename {src => Source}/resolver/ResolvedPostgresServerResource.ts (100%) rename {src => Source}/table/tree/TableAccountTreeItem.ts (100%) rename {src => Source}/tree/AttachedAccountsTreeItem.ts (100%) rename {src => Source}/tree/AzureAccountTreeItemWithAttached.ts (100%) rename {src => Source}/tree/AzureDBAPIStep.ts (100%) rename {src => Source}/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts (100%) rename {src => Source}/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts (100%) rename {src => Source}/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts (100%) rename {src => Source}/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts (100%) rename {src => Source}/tree/IAzureDBWizardContext.ts (100%) rename {src => Source}/tree/SubscriptionTreeItem.ts (100%) rename {src => Source}/utils/InteractiveChildProcess.ts (100%) rename {src => Source}/utils/activityUtils.ts (100%) rename {src => Source}/utils/array.ts (100%) rename {src => Source}/utils/azureClients.ts (100%) rename {src => Source}/utils/azureUtils.ts (100%) rename {src => Source}/utils/cp.ts (100%) rename {src => Source}/utils/getIp.ts (100%) rename {src => Source}/utils/getSecretStorageKey.ts (98%) rename {src => Source}/utils/improveError.ts (100%) rename {src => Source}/utils/localize.ts (100%) rename {src => Source}/utils/nonNull.ts (100%) rename {src => Source}/utils/openUrl.ts (100%) rename {src => Source}/utils/randomUtils.ts (100%) rename {src => Source}/utils/settingUtils.ts (100%) rename {src => Source}/utils/timeout.ts (100%) rename {src => Source}/utils/vscodeUtils.ts (100%) rename {src => Source}/utils/workspacUtils.ts (100%) rename {src => Source}/utils/wrapError.ts (100%) rename {src => Source}/vscode-cosmosdb.api.d.ts (100%) rename {src => Source}/vscode-cosmosdbgraph.api.d.ts (100%) diff --git a/src/AzureDBExperiences.ts b/Source/AzureDBExperiences.ts similarity index 100% rename from src/AzureDBExperiences.ts rename to Source/AzureDBExperiences.ts diff --git a/src/DatabasesFileSystem.ts b/Source/DatabasesFileSystem.ts similarity index 100% rename from src/DatabasesFileSystem.ts rename to Source/DatabasesFileSystem.ts diff --git a/src/ParsedConnectionString.ts b/Source/ParsedConnectionString.ts similarity index 100% rename from src/ParsedConnectionString.ts rename to Source/ParsedConnectionString.ts diff --git a/src/azureAccountUtils.ts b/Source/azureAccountUtils.ts similarity index 100% rename from src/azureAccountUtils.ts rename to Source/azureAccountUtils.ts diff --git a/src/commands/api/DatabaseAccountTreeItemInternal.ts b/Source/commands/api/DatabaseAccountTreeItemInternal.ts similarity index 100% rename from src/commands/api/DatabaseAccountTreeItemInternal.ts rename to Source/commands/api/DatabaseAccountTreeItemInternal.ts diff --git a/src/commands/api/DatabaseTreeItemInternal.ts b/Source/commands/api/DatabaseTreeItemInternal.ts similarity index 100% rename from src/commands/api/DatabaseTreeItemInternal.ts rename to Source/commands/api/DatabaseTreeItemInternal.ts diff --git a/src/commands/api/apiCache.ts b/Source/commands/api/apiCache.ts similarity index 100% rename from src/commands/api/apiCache.ts rename to Source/commands/api/apiCache.ts diff --git a/src/commands/api/findTreeItem.ts b/Source/commands/api/findTreeItem.ts similarity index 100% rename from src/commands/api/findTreeItem.ts rename to Source/commands/api/findTreeItem.ts diff --git a/src/commands/api/pickTreeItem.ts b/Source/commands/api/pickTreeItem.ts similarity index 100% rename from src/commands/api/pickTreeItem.ts rename to Source/commands/api/pickTreeItem.ts diff --git a/src/commands/api/revealTreeItem.ts b/Source/commands/api/revealTreeItem.ts similarity index 100% rename from src/commands/api/revealTreeItem.ts rename to Source/commands/api/revealTreeItem.ts diff --git a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts similarity index 100% rename from src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts rename to Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts diff --git a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts similarity index 100% rename from src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts rename to Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts diff --git a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts similarity index 100% rename from src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts rename to Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts diff --git a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts similarity index 100% rename from src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts rename to Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts diff --git a/src/commands/importDocuments.ts b/Source/commands/importDocuments.ts similarity index 100% rename from src/commands/importDocuments.ts rename to Source/commands/importDocuments.ts diff --git a/src/constants.ts b/Source/constants.ts similarity index 100% rename from src/constants.ts rename to Source/constants.ts diff --git a/src/docdb/docDBConnectionStrings.ts b/Source/docdb/docDBConnectionStrings.ts similarity index 100% rename from src/docdb/docDBConnectionStrings.ts rename to Source/docdb/docDBConnectionStrings.ts diff --git a/src/docdb/getCosmosClient.ts b/Source/docdb/getCosmosClient.ts similarity index 100% rename from src/docdb/getCosmosClient.ts rename to Source/docdb/getCosmosClient.ts diff --git a/src/docdb/registerDocDBCommands.ts b/Source/docdb/registerDocDBCommands.ts similarity index 100% rename from src/docdb/registerDocDBCommands.ts rename to Source/docdb/registerDocDBCommands.ts diff --git a/src/docdb/tree/DocDBAccountTreeItem.ts b/Source/docdb/tree/DocDBAccountTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBAccountTreeItem.ts rename to Source/docdb/tree/DocDBAccountTreeItem.ts diff --git a/src/docdb/tree/DocDBAccountTreeItemBase.ts b/Source/docdb/tree/DocDBAccountTreeItemBase.ts similarity index 100% rename from src/docdb/tree/DocDBAccountTreeItemBase.ts rename to Source/docdb/tree/DocDBAccountTreeItemBase.ts diff --git a/src/docdb/tree/DocDBCollectionTreeItem.ts b/Source/docdb/tree/DocDBCollectionTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBCollectionTreeItem.ts rename to Source/docdb/tree/DocDBCollectionTreeItem.ts diff --git a/src/docdb/tree/DocDBDatabaseTreeItem.ts b/Source/docdb/tree/DocDBDatabaseTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBDatabaseTreeItem.ts rename to Source/docdb/tree/DocDBDatabaseTreeItem.ts diff --git a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts similarity index 100% rename from src/docdb/tree/DocDBDatabaseTreeItemBase.ts rename to Source/docdb/tree/DocDBDatabaseTreeItemBase.ts diff --git a/src/docdb/tree/DocDBDocumentTreeItem.ts b/Source/docdb/tree/DocDBDocumentTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBDocumentTreeItem.ts rename to Source/docdb/tree/DocDBDocumentTreeItem.ts diff --git a/src/docdb/tree/DocDBDocumentsTreeItem.ts b/Source/docdb/tree/DocDBDocumentsTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBDocumentsTreeItem.ts rename to Source/docdb/tree/DocDBDocumentsTreeItem.ts diff --git a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBStoredProcedureTreeItem.ts rename to Source/docdb/tree/DocDBStoredProcedureTreeItem.ts diff --git a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts similarity index 100% rename from src/docdb/tree/DocDBStoredProceduresTreeItem.ts rename to Source/docdb/tree/DocDBStoredProceduresTreeItem.ts diff --git a/src/docdb/tree/DocDBTreeItemBase.ts b/Source/docdb/tree/DocDBTreeItemBase.ts similarity index 100% rename from src/docdb/tree/DocDBTreeItemBase.ts rename to Source/docdb/tree/DocDBTreeItemBase.ts diff --git a/src/docdb/tree/DocDBUtils.ts b/Source/docdb/tree/DocDBUtils.ts similarity index 100% rename from src/docdb/tree/DocDBUtils.ts rename to Source/docdb/tree/DocDBUtils.ts diff --git a/src/docdb/tree/IDocDBTreeRoot.ts b/Source/docdb/tree/IDocDBTreeRoot.ts similarity index 100% rename from src/docdb/tree/IDocDBTreeRoot.ts rename to Source/docdb/tree/IDocDBTreeRoot.ts diff --git a/src/extension.ts b/Source/extension.ts similarity index 100% rename from src/extension.ts rename to Source/extension.ts diff --git a/src/extensionVariables.ts b/Source/extensionVariables.ts similarity index 100% rename from src/extensionVariables.ts rename to Source/extensionVariables.ts diff --git a/src/getExtensionApi.ts b/Source/getExtensionApi.ts similarity index 100% rename from src/getExtensionApi.ts rename to Source/getExtensionApi.ts diff --git a/src/graph/gremlinEndpoints.ts b/Source/graph/gremlinEndpoints.ts similarity index 100% rename from src/graph/gremlinEndpoints.ts rename to Source/graph/gremlinEndpoints.ts diff --git a/src/graph/registerGraphCommands.ts b/Source/graph/registerGraphCommands.ts similarity index 100% rename from src/graph/registerGraphCommands.ts rename to Source/graph/registerGraphCommands.ts diff --git a/src/graph/tree/GraphAccountTreeItem.ts b/Source/graph/tree/GraphAccountTreeItem.ts similarity index 100% rename from src/graph/tree/GraphAccountTreeItem.ts rename to Source/graph/tree/GraphAccountTreeItem.ts diff --git a/src/graph/tree/GraphCollectionTreeItem.ts b/Source/graph/tree/GraphCollectionTreeItem.ts similarity index 100% rename from src/graph/tree/GraphCollectionTreeItem.ts rename to Source/graph/tree/GraphCollectionTreeItem.ts diff --git a/src/graph/tree/GraphDatabaseTreeItem.ts b/Source/graph/tree/GraphDatabaseTreeItem.ts similarity index 100% rename from src/graph/tree/GraphDatabaseTreeItem.ts rename to Source/graph/tree/GraphDatabaseTreeItem.ts diff --git a/src/graph/tree/GraphTreeItem.ts b/Source/graph/tree/GraphTreeItem.ts similarity index 100% rename from src/graph/tree/GraphTreeItem.ts rename to Source/graph/tree/GraphTreeItem.ts diff --git a/src/mongo/MongoCommand.ts b/Source/mongo/MongoCommand.ts similarity index 100% rename from src/mongo/MongoCommand.ts rename to Source/mongo/MongoCommand.ts diff --git a/src/mongo/MongoScrapbook.ts b/Source/mongo/MongoScrapbook.ts similarity index 100% rename from src/mongo/MongoScrapbook.ts rename to Source/mongo/MongoScrapbook.ts diff --git a/src/mongo/MongoShell.ts b/Source/mongo/MongoShell.ts similarity index 100% rename from src/mongo/MongoShell.ts rename to Source/mongo/MongoShell.ts diff --git a/src/mongo/connectToMongoClient.ts b/Source/mongo/connectToMongoClient.ts similarity index 100% rename from src/mongo/connectToMongoClient.ts rename to Source/mongo/connectToMongoClient.ts diff --git a/src/mongo/errorListeners.ts b/Source/mongo/errorListeners.ts similarity index 100% rename from src/mongo/errorListeners.ts rename to Source/mongo/errorListeners.ts diff --git a/src/mongo/grammar/mongo.tokens b/Source/mongo/grammar/mongo.tokens similarity index 100% rename from src/mongo/grammar/mongo.tokens rename to Source/mongo/grammar/mongo.tokens diff --git a/src/mongo/grammar/mongoLexer.tokens b/Source/mongo/grammar/mongoLexer.tokens similarity index 100% rename from src/mongo/grammar/mongoLexer.tokens rename to Source/mongo/grammar/mongoLexer.tokens diff --git a/src/mongo/grammar/mongoLexer.ts b/Source/mongo/grammar/mongoLexer.ts similarity index 100% rename from src/mongo/grammar/mongoLexer.ts rename to Source/mongo/grammar/mongoLexer.ts diff --git a/src/mongo/grammar/mongoListener.ts b/Source/mongo/grammar/mongoListener.ts similarity index 100% rename from src/mongo/grammar/mongoListener.ts rename to Source/mongo/grammar/mongoListener.ts diff --git a/src/mongo/grammar/mongoParser.ts b/Source/mongo/grammar/mongoParser.ts similarity index 100% rename from src/mongo/grammar/mongoParser.ts rename to Source/mongo/grammar/mongoParser.ts diff --git a/src/mongo/grammar/mongoVisitor.ts b/Source/mongo/grammar/mongoVisitor.ts similarity index 100% rename from src/mongo/grammar/mongoVisitor.ts rename to Source/mongo/grammar/mongoVisitor.ts diff --git a/src/mongo/grammar/visitors.ts b/Source/mongo/grammar/visitors.ts similarity index 100% rename from src/mongo/grammar/visitors.ts rename to Source/mongo/grammar/visitors.ts diff --git a/src/mongo/languageClient.ts b/Source/mongo/languageClient.ts similarity index 100% rename from src/mongo/languageClient.ts rename to Source/mongo/languageClient.ts diff --git a/src/mongo/languageServer.ts b/Source/mongo/languageServer.ts similarity index 100% rename from src/mongo/languageServer.ts rename to Source/mongo/languageServer.ts diff --git a/src/mongo/mongoConnectionStrings.ts b/Source/mongo/mongoConnectionStrings.ts similarity index 100% rename from src/mongo/mongoConnectionStrings.ts rename to Source/mongo/mongoConnectionStrings.ts diff --git a/src/mongo/registerMongoCommands.ts b/Source/mongo/registerMongoCommands.ts similarity index 100% rename from src/mongo/registerMongoCommands.ts rename to Source/mongo/registerMongoCommands.ts diff --git a/src/mongo/services/IConnectionParams.ts b/Source/mongo/services/IConnectionParams.ts similarity index 100% rename from src/mongo/services/IConnectionParams.ts rename to Source/mongo/services/IConnectionParams.ts diff --git a/src/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts similarity index 100% rename from src/mongo/services/MongoCodeLensProvider.ts rename to Source/mongo/services/MongoCodeLensProvider.ts diff --git a/src/mongo/services/completionItemProvider.ts b/Source/mongo/services/completionItemProvider.ts similarity index 100% rename from src/mongo/services/completionItemProvider.ts rename to Source/mongo/services/completionItemProvider.ts diff --git a/src/mongo/services/languageService.ts b/Source/mongo/services/languageService.ts similarity index 100% rename from src/mongo/services/languageService.ts rename to Source/mongo/services/languageService.ts diff --git a/src/mongo/services/mongoScript.ts b/Source/mongo/services/mongoScript.ts similarity index 100% rename from src/mongo/services/mongoScript.ts rename to Source/mongo/services/mongoScript.ts diff --git a/src/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts similarity index 100% rename from src/mongo/services/schemaService.ts rename to Source/mongo/services/schemaService.ts diff --git a/src/mongo/setConnectedNode.ts b/Source/mongo/setConnectedNode.ts similarity index 100% rename from src/mongo/setConnectedNode.ts rename to Source/mongo/setConnectedNode.ts diff --git a/src/mongo/tree/IMongoTreeRoot.ts b/Source/mongo/tree/IMongoTreeRoot.ts similarity index 100% rename from src/mongo/tree/IMongoTreeRoot.ts rename to Source/mongo/tree/IMongoTreeRoot.ts diff --git a/src/mongo/tree/MongoAccountTreeItem.ts b/Source/mongo/tree/MongoAccountTreeItem.ts similarity index 100% rename from src/mongo/tree/MongoAccountTreeItem.ts rename to Source/mongo/tree/MongoAccountTreeItem.ts diff --git a/src/mongo/tree/MongoCollectionTreeItem.ts b/Source/mongo/tree/MongoCollectionTreeItem.ts similarity index 100% rename from src/mongo/tree/MongoCollectionTreeItem.ts rename to Source/mongo/tree/MongoCollectionTreeItem.ts diff --git a/src/mongo/tree/MongoDatabaseTreeItem.ts b/Source/mongo/tree/MongoDatabaseTreeItem.ts similarity index 100% rename from src/mongo/tree/MongoDatabaseTreeItem.ts rename to Source/mongo/tree/MongoDatabaseTreeItem.ts diff --git a/src/mongo/tree/MongoDocumentTreeItem.ts b/Source/mongo/tree/MongoDocumentTreeItem.ts similarity index 100% rename from src/mongo/tree/MongoDocumentTreeItem.ts rename to Source/mongo/tree/MongoDocumentTreeItem.ts diff --git a/src/postgres/abstract/AbstractPostgresClient.ts b/Source/postgres/abstract/AbstractPostgresClient.ts similarity index 100% rename from src/postgres/abstract/AbstractPostgresClient.ts rename to Source/postgres/abstract/AbstractPostgresClient.ts diff --git a/src/postgres/abstract/models.ts b/Source/postgres/abstract/models.ts similarity index 100% rename from src/postgres/abstract/models.ts rename to Source/postgres/abstract/models.ts diff --git a/src/postgres/commands/checkAuthentication.ts b/Source/postgres/commands/checkAuthentication.ts similarity index 100% rename from src/postgres/commands/checkAuthentication.ts rename to Source/postgres/commands/checkAuthentication.ts diff --git a/src/postgres/commands/configurePostgresFirewall.ts b/Source/postgres/commands/configurePostgresFirewall.ts similarity index 100% rename from src/postgres/commands/configurePostgresFirewall.ts rename to Source/postgres/commands/configurePostgresFirewall.ts diff --git a/src/postgres/commands/connectPostgresDatabase.ts b/Source/postgres/commands/connectPostgresDatabase.ts similarity index 100% rename from src/postgres/commands/connectPostgresDatabase.ts rename to Source/postgres/commands/connectPostgresDatabase.ts diff --git a/src/postgres/commands/copyConnectionString.ts b/Source/postgres/commands/copyConnectionString.ts similarity index 100% rename from src/postgres/commands/copyConnectionString.ts rename to Source/postgres/commands/copyConnectionString.ts diff --git a/src/postgres/commands/createPostgresDatabase.ts b/Source/postgres/commands/createPostgresDatabase.ts similarity index 100% rename from src/postgres/commands/createPostgresDatabase.ts rename to Source/postgres/commands/createPostgresDatabase.ts diff --git a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts rename to Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts diff --git a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts rename to Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts diff --git a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts rename to Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts rename to Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts rename to Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts rename to Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts rename to Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts diff --git a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts rename to Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts rename to Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts rename to Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts rename to Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts diff --git a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts similarity index 100% rename from src/postgres/commands/createPostgresQuery/validateIdentifier.ts rename to Source/postgres/commands/createPostgresQuery/validateIdentifier.ts diff --git a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts rename to Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts similarity index 100% rename from src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts rename to Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts diff --git a/src/postgres/commands/deletePostgresDatabase.ts b/Source/postgres/commands/deletePostgresDatabase.ts similarity index 100% rename from src/postgres/commands/deletePostgresDatabase.ts rename to Source/postgres/commands/deletePostgresDatabase.ts diff --git a/src/postgres/commands/deletePostgresFunction.ts b/Source/postgres/commands/deletePostgresFunction.ts similarity index 100% rename from src/postgres/commands/deletePostgresFunction.ts rename to Source/postgres/commands/deletePostgresFunction.ts diff --git a/src/postgres/commands/deletePostgresServer.ts b/Source/postgres/commands/deletePostgresServer.ts similarity index 100% rename from src/postgres/commands/deletePostgresServer.ts rename to Source/postgres/commands/deletePostgresServer.ts diff --git a/src/postgres/commands/deletePostgresStoredProcedure.ts b/Source/postgres/commands/deletePostgresStoredProcedure.ts similarity index 100% rename from src/postgres/commands/deletePostgresStoredProcedure.ts rename to Source/postgres/commands/deletePostgresStoredProcedure.ts diff --git a/src/postgres/commands/deletePostgresTable.ts b/Source/postgres/commands/deletePostgresTable.ts similarity index 100% rename from src/postgres/commands/deletePostgresTable.ts rename to Source/postgres/commands/deletePostgresTable.ts diff --git a/src/postgres/commands/enterPostgresCredentials.ts b/Source/postgres/commands/enterPostgresCredentials.ts similarity index 100% rename from src/postgres/commands/enterPostgresCredentials.ts rename to Source/postgres/commands/enterPostgresCredentials.ts diff --git a/src/postgres/commands/executePostgresQueryInDocument.ts b/Source/postgres/commands/executePostgresQueryInDocument.ts similarity index 100% rename from src/postgres/commands/executePostgresQueryInDocument.ts rename to Source/postgres/commands/executePostgresQueryInDocument.ts diff --git a/src/postgres/commands/openPostgresFunction.ts b/Source/postgres/commands/openPostgresFunction.ts similarity index 100% rename from src/postgres/commands/openPostgresFunction.ts rename to Source/postgres/commands/openPostgresFunction.ts diff --git a/src/postgres/commands/openPostgresStoredProcedure.ts b/Source/postgres/commands/openPostgresStoredProcedure.ts similarity index 100% rename from src/postgres/commands/openPostgresStoredProcedure.ts rename to Source/postgres/commands/openPostgresStoredProcedure.ts diff --git a/src/postgres/commands/registerPostgresCommands.ts b/Source/postgres/commands/registerPostgresCommands.ts similarity index 100% rename from src/postgres/commands/registerPostgresCommands.ts rename to Source/postgres/commands/registerPostgresCommands.ts diff --git a/src/postgres/commands/setPostgresCredentials.ts b/Source/postgres/commands/setPostgresCredentials.ts similarity index 100% rename from src/postgres/commands/setPostgresCredentials.ts rename to Source/postgres/commands/setPostgresCredentials.ts diff --git a/src/postgres/getClientConfig.ts b/Source/postgres/getClientConfig.ts similarity index 100% rename from src/postgres/getClientConfig.ts rename to Source/postgres/getClientConfig.ts diff --git a/src/postgres/getPostgresProcedureQueryRows.ts b/Source/postgres/getPostgresProcedureQueryRows.ts similarity index 100% rename from src/postgres/getPostgresProcedureQueryRows.ts rename to Source/postgres/getPostgresProcedureQueryRows.ts diff --git a/src/postgres/getTables.ts b/Source/postgres/getTables.ts similarity index 100% rename from src/postgres/getTables.ts rename to Source/postgres/getTables.ts diff --git a/src/postgres/postgresConnectionStrings.ts b/Source/postgres/postgresConnectionStrings.ts similarity index 100% rename from src/postgres/postgresConnectionStrings.ts rename to Source/postgres/postgresConnectionStrings.ts diff --git a/src/postgres/postgresConstants.ts b/Source/postgres/postgresConstants.ts similarity index 100% rename from src/postgres/postgresConstants.ts rename to Source/postgres/postgresConstants.ts diff --git a/src/postgres/runPostgresQuery.ts b/Source/postgres/runPostgresQuery.ts similarity index 100% rename from src/postgres/runPostgresQuery.ts rename to Source/postgres/runPostgresQuery.ts diff --git a/src/postgres/services/PostgresCodeLensProvider.ts b/Source/postgres/services/PostgresCodeLensProvider.ts similarity index 100% rename from src/postgres/services/PostgresCodeLensProvider.ts rename to Source/postgres/services/PostgresCodeLensProvider.ts diff --git a/src/postgres/showPostgresQuery.ts b/Source/postgres/showPostgresQuery.ts similarity index 100% rename from src/postgres/showPostgresQuery.ts rename to Source/postgres/showPostgresQuery.ts diff --git a/src/postgres/tree/ClientConfigFactory.ts b/Source/postgres/tree/ClientConfigFactory.ts similarity index 100% rename from src/postgres/tree/ClientConfigFactory.ts rename to Source/postgres/tree/ClientConfigFactory.ts diff --git a/src/postgres/tree/PostgresColumnTreeItem.ts b/Source/postgres/tree/PostgresColumnTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresColumnTreeItem.ts rename to Source/postgres/tree/PostgresColumnTreeItem.ts diff --git a/src/postgres/tree/PostgresDatabaseTreeItem.ts b/Source/postgres/tree/PostgresDatabaseTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresDatabaseTreeItem.ts rename to Source/postgres/tree/PostgresDatabaseTreeItem.ts diff --git a/src/postgres/tree/PostgresFunctionTreeItem.ts b/Source/postgres/tree/PostgresFunctionTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresFunctionTreeItem.ts rename to Source/postgres/tree/PostgresFunctionTreeItem.ts diff --git a/src/postgres/tree/PostgresFunctionsTreeItem.ts b/Source/postgres/tree/PostgresFunctionsTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresFunctionsTreeItem.ts rename to Source/postgres/tree/PostgresFunctionsTreeItem.ts diff --git a/src/postgres/tree/PostgresResourcesTreeItemBase.ts b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts similarity index 100% rename from src/postgres/tree/PostgresResourcesTreeItemBase.ts rename to Source/postgres/tree/PostgresResourcesTreeItemBase.ts diff --git a/src/postgres/tree/PostgresServerTreeItem.ts b/Source/postgres/tree/PostgresServerTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresServerTreeItem.ts rename to Source/postgres/tree/PostgresServerTreeItem.ts diff --git a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresStoredProcedureTreeItem.ts rename to Source/postgres/tree/PostgresStoredProcedureTreeItem.ts diff --git a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresStoredProceduresTreeItem.ts rename to Source/postgres/tree/PostgresStoredProceduresTreeItem.ts diff --git a/src/postgres/tree/PostgresTableTreeItem.ts b/Source/postgres/tree/PostgresTableTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresTableTreeItem.ts rename to Source/postgres/tree/PostgresTableTreeItem.ts diff --git a/src/postgres/tree/PostgresTablesTreeItem.ts b/Source/postgres/tree/PostgresTablesTreeItem.ts similarity index 100% rename from src/postgres/tree/PostgresTablesTreeItem.ts rename to Source/postgres/tree/PostgresTablesTreeItem.ts diff --git a/src/resolver/AppResolver.ts b/Source/resolver/AppResolver.ts similarity index 100% rename from src/resolver/AppResolver.ts rename to Source/resolver/AppResolver.ts diff --git a/src/resolver/DatabaseWorkspaceProvider.ts b/Source/resolver/DatabaseWorkspaceProvider.ts similarity index 100% rename from src/resolver/DatabaseWorkspaceProvider.ts rename to Source/resolver/DatabaseWorkspaceProvider.ts diff --git a/src/resolver/ResolvedDatabaseAccountResource.ts b/Source/resolver/ResolvedDatabaseAccountResource.ts similarity index 100% rename from src/resolver/ResolvedDatabaseAccountResource.ts rename to Source/resolver/ResolvedDatabaseAccountResource.ts diff --git a/src/resolver/ResolvedDocDBAccountResource.ts b/Source/resolver/ResolvedDocDBAccountResource.ts similarity index 100% rename from src/resolver/ResolvedDocDBAccountResource.ts rename to Source/resolver/ResolvedDocDBAccountResource.ts diff --git a/src/resolver/ResolvedMongoAccountResource.ts b/Source/resolver/ResolvedMongoAccountResource.ts similarity index 100% rename from src/resolver/ResolvedMongoAccountResource.ts rename to Source/resolver/ResolvedMongoAccountResource.ts diff --git a/src/resolver/ResolvedPostgresServerResource.ts b/Source/resolver/ResolvedPostgresServerResource.ts similarity index 100% rename from src/resolver/ResolvedPostgresServerResource.ts rename to Source/resolver/ResolvedPostgresServerResource.ts diff --git a/src/table/tree/TableAccountTreeItem.ts b/Source/table/tree/TableAccountTreeItem.ts similarity index 100% rename from src/table/tree/TableAccountTreeItem.ts rename to Source/table/tree/TableAccountTreeItem.ts diff --git a/src/tree/AttachedAccountsTreeItem.ts b/Source/tree/AttachedAccountsTreeItem.ts similarity index 100% rename from src/tree/AttachedAccountsTreeItem.ts rename to Source/tree/AttachedAccountsTreeItem.ts diff --git a/src/tree/AzureAccountTreeItemWithAttached.ts b/Source/tree/AzureAccountTreeItemWithAttached.ts similarity index 100% rename from src/tree/AzureAccountTreeItemWithAttached.ts rename to Source/tree/AzureAccountTreeItemWithAttached.ts diff --git a/src/tree/AzureDBAPIStep.ts b/Source/tree/AzureDBAPIStep.ts similarity index 100% rename from src/tree/AzureDBAPIStep.ts rename to Source/tree/AzureDBAPIStep.ts diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts similarity index 100% rename from src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts rename to Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts similarity index 100% rename from src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts rename to Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts similarity index 100% rename from src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts rename to Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts diff --git a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts similarity index 100% rename from src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts rename to Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts diff --git a/src/tree/IAzureDBWizardContext.ts b/Source/tree/IAzureDBWizardContext.ts similarity index 100% rename from src/tree/IAzureDBWizardContext.ts rename to Source/tree/IAzureDBWizardContext.ts diff --git a/src/tree/SubscriptionTreeItem.ts b/Source/tree/SubscriptionTreeItem.ts similarity index 100% rename from src/tree/SubscriptionTreeItem.ts rename to Source/tree/SubscriptionTreeItem.ts diff --git a/src/utils/InteractiveChildProcess.ts b/Source/utils/InteractiveChildProcess.ts similarity index 100% rename from src/utils/InteractiveChildProcess.ts rename to Source/utils/InteractiveChildProcess.ts diff --git a/src/utils/activityUtils.ts b/Source/utils/activityUtils.ts similarity index 100% rename from src/utils/activityUtils.ts rename to Source/utils/activityUtils.ts diff --git a/src/utils/array.ts b/Source/utils/array.ts similarity index 100% rename from src/utils/array.ts rename to Source/utils/array.ts diff --git a/src/utils/azureClients.ts b/Source/utils/azureClients.ts similarity index 100% rename from src/utils/azureClients.ts rename to Source/utils/azureClients.ts diff --git a/src/utils/azureUtils.ts b/Source/utils/azureUtils.ts similarity index 100% rename from src/utils/azureUtils.ts rename to Source/utils/azureUtils.ts diff --git a/src/utils/cp.ts b/Source/utils/cp.ts similarity index 100% rename from src/utils/cp.ts rename to Source/utils/cp.ts diff --git a/src/utils/getIp.ts b/Source/utils/getIp.ts similarity index 100% rename from src/utils/getIp.ts rename to Source/utils/getIp.ts diff --git a/src/utils/getSecretStorageKey.ts b/Source/utils/getSecretStorageKey.ts similarity index 98% rename from src/utils/getSecretStorageKey.ts rename to Source/utils/getSecretStorageKey.ts index 80e116737..8e404f554 100644 --- a/src/utils/getSecretStorageKey.ts +++ b/Source/utils/getSecretStorageKey.ts @@ -1,8 +1,8 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; -} +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export function getSecretStorageKey(serviceName: string, id: string): string { + return `${serviceName}.${id}`; +} diff --git a/src/utils/improveError.ts b/Source/utils/improveError.ts similarity index 100% rename from src/utils/improveError.ts rename to Source/utils/improveError.ts diff --git a/src/utils/localize.ts b/Source/utils/localize.ts similarity index 100% rename from src/utils/localize.ts rename to Source/utils/localize.ts diff --git a/src/utils/nonNull.ts b/Source/utils/nonNull.ts similarity index 100% rename from src/utils/nonNull.ts rename to Source/utils/nonNull.ts diff --git a/src/utils/openUrl.ts b/Source/utils/openUrl.ts similarity index 100% rename from src/utils/openUrl.ts rename to Source/utils/openUrl.ts diff --git a/src/utils/randomUtils.ts b/Source/utils/randomUtils.ts similarity index 100% rename from src/utils/randomUtils.ts rename to Source/utils/randomUtils.ts diff --git a/src/utils/settingUtils.ts b/Source/utils/settingUtils.ts similarity index 100% rename from src/utils/settingUtils.ts rename to Source/utils/settingUtils.ts diff --git a/src/utils/timeout.ts b/Source/utils/timeout.ts similarity index 100% rename from src/utils/timeout.ts rename to Source/utils/timeout.ts diff --git a/src/utils/vscodeUtils.ts b/Source/utils/vscodeUtils.ts similarity index 100% rename from src/utils/vscodeUtils.ts rename to Source/utils/vscodeUtils.ts diff --git a/src/utils/workspacUtils.ts b/Source/utils/workspacUtils.ts similarity index 100% rename from src/utils/workspacUtils.ts rename to Source/utils/workspacUtils.ts diff --git a/src/utils/wrapError.ts b/Source/utils/wrapError.ts similarity index 100% rename from src/utils/wrapError.ts rename to Source/utils/wrapError.ts diff --git a/src/vscode-cosmosdb.api.d.ts b/Source/vscode-cosmosdb.api.d.ts similarity index 100% rename from src/vscode-cosmosdb.api.d.ts rename to Source/vscode-cosmosdb.api.d.ts diff --git a/src/vscode-cosmosdbgraph.api.d.ts b/Source/vscode-cosmosdbgraph.api.d.ts similarity index 100% rename from src/vscode-cosmosdbgraph.api.d.ts rename to Source/vscode-cosmosdbgraph.api.d.ts From 43e018bb81b3050228fd19f5e12c1ee1b5ce1b20 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Mon, 30 Oct 2023 12:08:32 +0200 Subject: [PATCH 08/33] squash! --- LICENSE.md | 42 +- NOTICE.html | 6617 +++++++++------ README.md | 267 +- Source/AzureDBExperiences.ts | 250 +- Source/DatabasesFileSystem.ts | 147 +- Source/ParsedConnectionString.ts | 36 +- Source/azureAccountUtils.ts | 27 +- .../api/DatabaseAccountTreeItemInternal.ts | 220 +- .../commands/api/DatabaseTreeItemInternal.ts | 93 +- Source/commands/api/apiCache.ts | 82 +- Source/commands/api/findTreeItem.ts | 355 +- Source/commands/api/pickTreeItem.ts | 220 +- Source/commands/api/revealTreeItem.ts | 29 +- .../DatabaseAccountDeleteStep.ts | 14 +- .../IDeleteWizardContext.ts | 25 +- .../deleteCosmosDBAccount.ts | 69 +- .../deleteDatabaseAccount.ts | 60 +- Source/commands/importDocuments.ts | 328 +- Source/constants.ts | 133 +- Source/docdb/docDBConnectionStrings.ts | 78 +- Source/docdb/getCosmosClient.ts | 35 +- Source/docdb/registerDocDBCommands.ts | 238 +- Source/docdb/tree/DocDBAccountTreeItem.ts | 56 +- Source/docdb/tree/DocDBAccountTreeItemBase.ts | 188 +- Source/docdb/tree/DocDBCollectionTreeItem.ts | 187 +- Source/docdb/tree/DocDBDatabaseTreeItem.ts | 31 +- .../docdb/tree/DocDBDatabaseTreeItemBase.ts | 329 +- Source/docdb/tree/DocDBDocumentTreeItem.ts | 286 +- Source/docdb/tree/DocDBDocumentsTreeItem.ts | 269 +- .../tree/DocDBStoredProcedureTreeItem.ts | 134 +- .../tree/DocDBStoredProceduresTreeItem.ts | 216 +- Source/docdb/tree/DocDBTreeItemBase.ts | 79 +- Source/docdb/tree/DocDBUtils.ts | 2 +- Source/docdb/tree/IDocDBTreeRoot.ts | 9 +- Source/extension.ts | 592 +- Source/extensionVariables.ts | 61 +- Source/getExtensionApi.ts | 41 +- Source/graph/gremlinEndpoints.ts | 74 +- Source/graph/registerGraphCommands.ts | 125 +- Source/graph/tree/GraphAccountTreeItem.ts | 87 +- Source/graph/tree/GraphCollectionTreeItem.ts | 181 +- Source/graph/tree/GraphDatabaseTreeItem.ts | 109 +- Source/graph/tree/GraphTreeItem.ts | 105 +- Source/mongo/MongoCommand.ts | 26 +- Source/mongo/MongoScrapbook.ts | 1135 ++- Source/mongo/MongoShell.ts | 353 +- Source/mongo/connectToMongoClient.ts | 87 +- Source/mongo/errorListeners.ts | 98 +- Source/mongo/grammar/mongoLexer.ts | 535 +- Source/mongo/grammar/mongoListener.ts | 36 +- Source/mongo/grammar/mongoParser.ts | 2994 +++---- Source/mongo/grammar/mongoVisitor.ts | 32 +- Source/mongo/grammar/visitors.ts | 157 +- Source/mongo/languageClient.ts | 120 +- Source/mongo/languageServer.ts | 4 +- Source/mongo/mongoConnectionStrings.ts | 158 +- Source/mongo/registerMongoCommands.ts | 500 +- Source/mongo/services/IConnectionParams.ts | 6 +- .../mongo/services/MongoCodeLensProvider.ts | 130 +- .../mongo/services/completionItemProvider.ts | 1015 ++- Source/mongo/services/languageService.ts | 193 +- Source/mongo/services/mongoScript.ts | 195 +- Source/mongo/services/schemaService.ts | 1336 +-- Source/mongo/setConnectedNode.ts | 10 +- Source/mongo/tree/IMongoTreeRoot.ts | 3 +- Source/mongo/tree/MongoAccountTreeItem.ts | 307 +- Source/mongo/tree/MongoCollectionTreeItem.ts | 753 +- Source/mongo/tree/MongoDatabaseTreeItem.ts | 611 +- Source/mongo/tree/MongoDocumentTreeItem.ts | 182 +- .../abstract/AbstractPostgresClient.ts | 30 +- Source/postgres/abstract/models.ts | 73 +- .../postgres/commands/checkAuthentication.ts | 56 +- .../commands/configurePostgresFirewall.ts | 128 +- .../commands/connectPostgresDatabase.ts | 70 +- .../postgres/commands/copyConnectionString.ts | 76 +- .../commands/createPostgresDatabase.ts | 49 +- .../IPostgresQueryWizardContext.ts | 5 +- .../IPostgresFunctionQueryWizardContext.ts | 5 +- .../function/createPostgresFunctionQuery.ts | 22 +- .../function/steps/FunctionQueryCreateStep.ts | 24 +- .../FunctionQueryCustomReturnTypeStep.ts | 19 +- .../function/steps/FunctionQueryNameStep.ts | 25 +- .../steps/FunctionQueryReturnTypeStep.ts | 87 +- .../runPostgresQueryWizard.ts | 29 +- .../createPostgresStoredProcedureQuery.ts | 17 +- .../steps/StoredProcedureQueryCreateStep.ts | 20 +- .../steps/StoredProcedureQueryNameStep.ts | 23 +- .../createPostgresQuery/validateIdentifier.ts | 203 +- .../IPostgresServerWizardContext.ts | 34 +- .../steps/PostgresServerConfirmPWStep.ts | 40 +- .../steps/PostgresServerCreateStep.ts | 205 +- .../steps/PostgresServerCredPWStep.ts | 99 +- .../steps/PostgresServerCredUserStep.ts | 100 +- .../steps/PostgresServerNameStep.ts | 143 +- .../steps/PostgresServerSetCredentialsStep.ts | 84 +- .../steps/PostgresServerSkuStep.ts | 465 +- .../commands/deletePostgresDatabase.ts | 61 +- .../commands/deletePostgresFunction.ts | 57 +- .../postgres/commands/deletePostgresServer.ts | 37 +- .../commands/deletePostgresStoredProcedure.ts | 60 +- .../postgres/commands/deletePostgresTable.ts | 56 +- .../commands/enterPostgresCredentials.ts | 153 +- .../executePostgresQueryInDocument.ts | 127 +- .../postgres/commands/openPostgresFunction.ts | 23 +- .../commands/openPostgresStoredProcedure.ts | 24 +- .../commands/registerPostgresCommands.ts | 166 +- .../commands/setPostgresCredentials.ts | 44 +- Source/postgres/getClientConfig.ts | 187 +- .../postgres/getPostgresProcedureQueryRows.ts | 61 +- Source/postgres/getTables.ts | 34 +- Source/postgres/postgresConnectionStrings.ts | 123 +- Source/postgres/postgresConstants.ts | 6 +- Source/postgres/runPostgresQuery.ts | 21 +- .../services/PostgresCodeLensProvider.ts | 122 +- Source/postgres/showPostgresQuery.ts | 16 +- Source/postgres/tree/ClientConfigFactory.ts | 171 +- .../postgres/tree/PostgresColumnTreeItem.ts | 41 +- .../postgres/tree/PostgresDatabaseTreeItem.ts | 252 +- .../postgres/tree/PostgresFunctionTreeItem.ts | 70 +- .../tree/PostgresFunctionsTreeItem.ts | 70 +- .../tree/PostgresResourcesTreeItemBase.ts | 26 +- .../postgres/tree/PostgresServerTreeItem.ts | 611 +- .../tree/PostgresStoredProcedureTreeItem.ts | 68 +- .../tree/PostgresStoredProceduresTreeItem.ts | 74 +- Source/postgres/tree/PostgresTableTreeItem.ts | 92 +- .../postgres/tree/PostgresTablesTreeItem.ts | 81 +- Source/resolver/AppResolver.ts | 149 +- Source/resolver/DatabaseWorkspaceProvider.ts | 48 +- .../ResolvedDatabaseAccountResource.ts | 117 +- .../resolver/ResolvedDocDBAccountResource.ts | 63 +- .../resolver/ResolvedMongoAccountResource.ts | 22 +- .../ResolvedPostgresServerResource.ts | 79 +- Source/table/tree/TableAccountTreeItem.ts | 50 +- Source/tree/AttachedAccountsTreeItem.ts | 973 ++- .../tree/AzureAccountTreeItemWithAttached.ts | 65 +- Source/tree/AzureDBAPIStep.ts | 159 +- .../CosmosDBAccountCapacityStep.ts | 73 +- .../CosmosDBAccountCreateStep.ts | 130 +- .../CosmosDBAccountNameStep.ts | 85 +- .../ICosmosDBWizardContext.ts | 24 +- Source/tree/IAzureDBWizardContext.ts | 10 +- Source/tree/SubscriptionTreeItem.ts | 460 +- Source/utils/InteractiveChildProcess.ts | 336 +- Source/utils/activityUtils.ts | 13 +- Source/utils/array.ts | 18 +- Source/utils/azureClients.ts | 39 +- Source/utils/azureUtils.ts | 12 +- Source/utils/cp.ts | 17 +- Source/utils/getIp.ts | 106 +- Source/utils/getSecretStorageKey.ts | 2 +- Source/utils/improveError.ts | 14 +- Source/utils/localize.ts | 2 +- Source/utils/nonNull.ts | 49 +- Source/utils/openUrl.ts | 8 +- Source/utils/randomUtils.ts | 17 +- Source/utils/settingUtils.ts | 98 +- Source/utils/timeout.ts | 70 +- Source/utils/vscodeUtils.ts | 180 +- Source/utils/workspacUtils.ts | 21 +- Source/utils/wrapError.ts | 26 +- Source/vscode-cosmosdb.api.d.ts | 154 +- Source/vscode-cosmosdbgraph.api.d.ts | 26 +- build/vscode-languageserver-files-stub.js | 52 +- extension.bundle.ts | 84 +- grammar/JavaScript.tmLanguage.json | 7420 ++++++++--------- grammar/Readme.md | 9 +- grammar/configuration.json | 90 +- gulpfile.ts | 39 +- main.js | 14 +- package.json | 2250 ++--- .../icons/theme-agnostic/CosmosDBAccount.svg | 55 +- .../icons/theme-agnostic/PostgresServer.svg | 28 +- test/attachedAccountsTreeItem.test.ts | 48 +- test/docDBConnectionStrings.test.ts | 194 +- test/documentLabel.test.ts | 36 +- test/global.test.ts | 20 +- test/improveError.test.ts | 31 +- test/index.ts | 87 +- test/mongoConnectionStrings.test.ts | 636 +- test/mongoGetCommand.test.ts | 2569 +++--- test/mongoShell.test.ts | 605 +- test/postgresConnectionStrings.test.ts | 72 +- test/runTest.ts | 76 +- test/runWithSetting.ts | 46 +- test/test.code-workspace | 12 +- test/timeout.test.ts | 232 +- test/unit/DocDBUtils.test.ts | 14 +- test/unit/getClientConfig.test.ts | 376 +- test/util/getIp.test.ts | 78 +- test/util/setEnvironmentVariables.test.ts | 42 +- test/util/setEnvironmentVariables.ts | 41 +- test/wrapError.test.ts | 105 +- tsconfig.json | 52 +- webpack.config.js | 76 +- 194 files changed, 27356 insertions(+), 20415 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 4b1ad51b2..21071075c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,21 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/NOTICE.html b/NOTICE.html index 7500e9041..78b671fd0 100644 --- a/NOTICE.html +++ b/NOTICE.html @@ -1,186 +1,226 @@ - - - - NOTICES AND INFORMATION - - - -

NOTICES AND INFORMATION

-

Do Not Translate or Localize

-

- This software incorporates material from third parties. - Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, - or you may send a check or money order for US $5.00, including the product name, - the open source component name, platform, and version number, to: -

-
- Source Code Compliance Team
- Microsoft Corporation
- One Microsoft Way
- Redmond, WA 98052
- USA -
-

- Notwithstanding any other terms, you may reverse engineer this software to the extent - required to debug changes to any libraries licensed under the GNU Lesser General Public License. -

-
    -
  1. -
    - - tslib 1.14.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  2. -
  3. -
    - - tslib 2.1.0 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  4. -
  5. -
    - - tslib 2.3.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  6. -
  7. -
    - - tslib 2.4.0 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  8. -
  9. -
    - - tslib 2.6.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  10. -
  11. -
    - - tslib 2.6.2 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  12. -
  13. -
    - - bson 1.1.4 - Apache-2.0 - -

    https://github.com/mongodb/js-bson#readme

    -
    • Copyright 2009 Google Inc.
    • -
    • Copyright (c) 2014, Facebook, Inc.
    • -
    • copyright (c) 2019 Denis Pushkarev
    • -
    • Copyright (c) 2008, Fair Oaks Labs, Inc.
    • -
    • Copyright Joyent, Inc. and other Node contributors.
    -
    +
    +
    +	
    +		NOTICES AND INFORMATION
    +		
    +	
    +	
    +		

    NOTICES AND INFORMATION

    +

    Do Not Translate or Localize

    +

    + This software incorporates material from third parties. Microsoft + makes certain open source code available at + https://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including + the product name, the open source component name, platform, and + version number, to: +

    +
    + Source Code Compliance Team
    + Microsoft Corporation
    + One Microsoft Way
    + Redmond, WA 98052
    + USA +
    +

    + Notwithstanding any other terms, you may reverse engineer this + software to the extent required to debug changes to any libraries + licensed under the GNU Lesser General Public License. +

    +
      +
    1. +
      + tslib 1.14.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    2. +
    3. +
      + tslib 2.1.0 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    4. +
    5. +
      + tslib 2.3.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    6. +
    7. +
      + tslib 2.4.0 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    8. +
    9. +
      + tslib 2.6.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    10. +
    11. +
      + tslib 2.6.2 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    12. +
    13. +
      + bson 1.1.4 - Apache-2.0 +

      + https://github.com/mongodb/js-bson#readme +

      +
        +
      • Copyright 2009 Google Inc.
      • +
      • Copyright (c) 2014, Facebook, Inc.
      • +
      • copyright (c) 2019 Denis Pushkarev
      • +
      • Copyright (c) 2008, Fair Oaks Labs, Inc.
      • +
      • + Copyright Joyent, Inc. and other Node contributors. +
      • +
      +
                                                Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -382,18 +422,23 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    14. -
    15. -
      - - denque 1.4.1 - Apache-2.0 - -

      https://github.com/invertase/denque#readme

      -
      • Copyright (c) 2018 Mike Diarmid
      -
      +
      +        
      +
      +
    16. +
    17. +
      + denque 1.4.1 - Apache-2.0 +

      + https://github.com/invertase/denque#readme +

      +
        +
      • Copyright (c) 2018 Mike Diarmid
      • +
      +
               Copyright (c) 2018 Mike Diarmid (Salakar) <mike.diarmid@gmail.com>
       
       Licensed under the Apache License, Version 2.0 (the "License");
      @@ -407,18 +452,22 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    18. -
    19. -
      - - jsbi 3.2.5 - Apache-2.0 - -

      https://github.com/GoogleChromeLabs/jsbi#readme

      - -
      +
      +        
      +
      +
    20. +
    21. +
      + jsbi 3.2.5 - Apache-2.0 +

      + https://github.com/GoogleChromeLabs/jsbi#readme +

      + +
                                                Apache License
                                  Version 2.0, January 2004
                               https://www.apache.org/licenses/
      @@ -595,19 +644,24 @@ 

      NOTICES AND INFORMATION

      of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS - -
      -
      -
    22. -
    23. -
      - - mongodb 3.6.10 - Apache-2.0 - -

      https://github.com/mongodb/node-mongodb-native

      -
      • (c) 2012-present MongoDB
      • -
      • (c) 2009-2012 Christian Amor Kvalheim
      -
      +
      +        
      +
      +
    24. +
    25. +
      + mongodb 3.6.10 - Apache-2.0 +

      + https://github.com/mongodb/node-mongodb-native +

      +
        +
      • (c) 2012-present MongoDB
      • +
      • (c) 2009-2012 Christian Amor Kvalheim
      • +
      +
               Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -808,18 +862,23 @@ 

      NOTICES AND INFORMATION

      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. -
      -
      -
    26. -
    27. -
      - - mongodb-extended-json 1.11.0 - Apache-2.0 - -

      http://github.com/mongodb-js/extended-json

      -
      • Copyright 2015 MongoDB Inc.
      -
      +   limitations under the License.
      +        
      +
      +
    28. +
    29. +
      + mongodb-extended-json 1.11.0 - Apache-2.0 +

      + http://github.com/mongodb-js/extended-json +

      +
        +
      • Copyright 2015 MongoDB Inc.
      • +
      +
               Apache License
       Version 2.0, January 2004
       http://www.apache.org/licenses/
      @@ -1021,18 +1080,24 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    30. -
    31. -
      - - optional-require 1.1.8 - Apache-2.0 - -

      https://github.com/jchip/optional-require#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +
      +        
      +
      +
    32. +
    33. +
      + optional-require 1.1.8 - Apache-2.0 +

      + https://github.com/jchip/optional-require#readme +

      +
        +
      • (c) Joel Chen (https://github.com/jchip)
      • +
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1129,18 +1194,23 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and -limitations under the License. -
      -
      -
    34. -
    35. -
      - - require-at 1.0.6 - Apache-2.0 - -

      https://github.com/jchip/require-at#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +limitations under the License.
      +        
      +
      +
    36. +
    37. +
      + require-at 1.0.6 - Apache-2.0 +

      + https://github.com/jchip/require-at#readme +

      +
        +
      • (c) Joel Chen (https://github.com/jchip)
      • +
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1237,18 +1307,23 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and -limitations under the License. -
      -
      -
    38. -
    39. -
      - - domelementtype 2.3.0 - BSD-2-Clause - -

      https://github.com/fb55/domelementtype#readme

      -
      • Copyright (c) Felix Bohm
      -
      +limitations under the License.
      +        
      +
      +
    40. +
    41. +
      + domelementtype 2.3.0 - BSD-2-Clause +

      + https://github.com/fb55/domelementtype#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1260,18 +1335,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    42. -
    43. -
      - - domhandler 4.3.1 - BSD-2-Clause - -

      https://github.com/fb55/domhandler#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    44. +
    45. +
      + domhandler 4.3.1 - BSD-2-Clause +

      + https://github.com/fb55/domhandler#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1283,18 +1363,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    46. -
    47. -
      - - domutils 2.8.0 - BSD-2-Clause - -

      https://github.com/fb55/domutils#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    48. +
    49. +
      + domutils 2.8.0 - BSD-2-Clause +

      + https://github.com/fb55/domutils#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1306,18 +1391,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    50. -
    51. -
      - - dotenv 8.6.0 - BSD-2-Clause - -

      https://github.com/motdotla/dotenv#readme

      -
      • Copyright (c) 2015, Scott Motte
      -
      +
      +        
      +
      +
    52. +
    53. +
      + dotenv 8.6.0 - BSD-2-Clause +

      + https://github.com/motdotla/dotenv#readme +

      +
        +
      • Copyright (c) 2015, Scott Motte
      • +
      +
               Copyright (c) 2015, Scott Motte
       All rights reserved.
       
      @@ -1341,18 +1431,23 @@ 

      NOTICES AND INFORMATION

      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    54. -
    55. -
      - - entities 2.2.0 - BSD-2-Clause - -

      https://github.com/fb55/entities#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    56. +
    57. +
      + entities 2.2.0 - BSD-2-Clause +

      + https://github.com/fb55/entities#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1364,18 +1459,24 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    58. -
    59. -
      - - webidl-conversions 3.0.1 - BSD-2-Clause - -

      https://github.com/jsdom/webidl-conversions#readme

      -
      • Copyright (c) 2014, Domenic Denicola
      -
      +
      +        
      +
      +
    60. +
    61. +
      + webidl-conversions 3.0.1 - BSD-2-Clause +

      + https://github.com/jsdom/webidl-conversions#readme +

      +
        +
      • Copyright (c) 2014, Domenic Denicola
      • +
      +
               # The BSD 2-Clause License
       
       Copyright (c) 2014, Domenic Denicola
      @@ -1388,58 +1489,69 @@ 

      NOTICES AND INFORMATION

      2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    62. -
    63. -
      - - antlr4ts 0.4.1-alpha.0 - BSD-3-Clause - -

      https://github.com/tunnelvisionlabs/antlr4ts#readme

      -
      • Copyright 2016 The ANTLR Project.
      • -
      • Copyright (c) 2016 The ANTLR Project
      -
      -        [The "BSD license"]
      -Copyright (c) 2016 The ANTLR Project
      -All rights reserved.
      -
      -Redistribution and use in source and binary forms, with or without
      -modification, are permitted provided that the following conditions
      -are met:
      -
      - 1. Redistributions of source code must retain the above copyright
      -    notice, this list of conditions and the following disclaimer.
      - 2. Redistributions in binary form must reproduce the above copyright
      -    notice, this list of conditions and the following disclaimer in the
      -    documentation and/or other materials provided with the distribution.
      - 3. Neither the name of the copyright holder nor the names of its
      -    contributors may be used to endorse or promote products derived from
      -    this software without specific prior written permission.
      -
      -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      -
      -        
      -
      -
    64. -
    65. -
      - - moo 0.5.1 - BSD-3-Clause - -

      https://github.com/tjvr/moo#readme

      -
      • Copyright (c) 2017, Tim Radvan
      -
      +
      +        
      +
      +
    66. +
    67. +
      + antlr4ts 0.4.1-alpha.0 - BSD-3-Clause +

      + https://github.com/tunnelvisionlabs/antlr4ts#readme +

      +
        +
      • Copyright 2016 The ANTLR Project.
      • +
      • Copyright (c) 2016 The ANTLR Project
      • +
      +
      +        [The "BSD license"]
      +Copyright (c) 2016 The ANTLR Project
      +All rights reserved.
      +
      +Redistribution and use in source and binary forms, with or without
      +modification, are permitted provided that the following conditions
      +are met:
      +
      + 1. Redistributions of source code must retain the above copyright
      +    notice, this list of conditions and the following disclaimer.
      + 2. Redistributions in binary form must reproduce the above copyright
      +    notice, this list of conditions and the following disclaimer in the
      +    documentation and/or other materials provided with the distribution.
      + 3. Neither the name of the copyright holder nor the names of its
      +    contributors may be used to endorse or promote products derived from
      +    this software without specific prior written permission.
      +
      +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      +
      +        
      +
      +
    68. +
    69. +
      + moo 0.5.1 - BSD-3-Clause +

      + https://github.com/tjvr/moo#readme +

      +
        +
      • Copyright (c) 2017, Tim Radvan
      • +
      +
               BSD 3-Clause License
       
       Copyright (c) 2017, Tim Radvan (tjvr)
      @@ -1469,18 +1581,21 @@ 

      NOTICES AND INFORMATION

      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    70. -
    71. -
      - - railroad-diagrams 1.0.0 - CC0-1.0 - -

      https://github.com/tabatkins/railroad-diagrams

      - -
      +
      +        
      +
      +
    72. +
    73. +
      + railroad-diagrams 1.0.0 - CC0-1.0 +

      + https://github.com/tabatkins/railroad-diagrams +

      + +
               Creative Commons Legal Code
       
       CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
      @@ -1521,18 +1636,27 @@ 

      NOTICES AND INFORMATION

      c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. - d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. -
      -
      -
    74. -
    75. -
      - - graceful-fs 4.2.10 - ISC - -

      https://github.com/isaacs/node-graceful-fs#readme

      -
      • Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      -
      +      d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
      +        
      +
      +
    76. +
    77. +
      + graceful-fs 4.2.10 - ISC +

      + https://github.com/isaacs/node-graceful-fs#readme +

      +
        +
      • + Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben + Noordhuis, and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      @@ -1548,18 +1672,23 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    78. -
    79. -
      - - inherits 2.0.4 - ISC - -

      https://github.com/isaacs/inherits#readme

      -
      • Copyright (c) Isaac Z. Schlueter
      -
      +
      +        
      +
      +
    80. +
    81. +
      + inherits 2.0.4 - ISC +

      + https://github.com/isaacs/inherits#readme +

      +
        +
      • Copyright (c) Isaac Z. Schlueter
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter
      @@ -1576,18 +1705,26 @@ 

      NOTICES AND INFORMATION

      OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    82. -
    83. -
      - - lru-cache 6.0.0 - ISC - -

      https://github.com/isaacs/node-lru-cache#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    84. +
    85. +
      + lru-cache 6.0.0 - ISC +

      + https://github.com/isaacs/node-lru-cache#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1603,18 +1740,23 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    86. -
    87. -
      - - pg-int8 1.0.1 - ISC - -

      https://github.com/charmander/pg-int8#readme

      -
      • Copyright (c) 2017, Charmander
      -
      +
      +        
      +
      +
    88. +
    89. +
      + pg-int8 1.0.1 - ISC +

      + https://github.com/charmander/pg-int8#readme +

      +
        +
      • Copyright (c) 2017, Charmander
      • +
      +
               Copyright © 2017, Charmander <~@charmander.me>
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -1628,19 +1770,29 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    90. -
    91. -
      - - sax 1.2.4 - ISC - -

      https://github.com/isaacs/sax-js#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      • -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +
      +        
      +
      +
    92. +
    93. +
      + sax 1.2.4 - ISC +

      + https://github.com/isaacs/sax-js#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      • + Copyright Mathias Bynens + <https://mathiasbynens.be/> +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1682,20 +1834,27 @@ 

      NOTICES AND INFORMATION

      LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    94. -
    95. -
      - - semver 6.3.0 - ISC - -

      https://github.com/npm/node-semver#readme

      -
      • Copyright Isaac Z.
      • -
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    96. +
    97. +
      + semver 6.3.0 - ISC +

      + https://github.com/npm/node-semver#readme +

      +
        +
      • Copyright Isaac Z.
      • +
      • Copyright Isaac Z. Schlueter
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1711,19 +1870,26 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    98. -
    99. -
      - - semver 7.5.2 - ISC - -

      https://github.com/npm/node-semver#readme

      -
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    100. +
    101. +
      + semver 7.5.2 - ISC +

      + https://github.com/npm/node-semver#readme +

      +
        +
      • Copyright Isaac Z. Schlueter
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1739,18 +1905,27 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    102. -
    103. -
      - - universal-user-agent 6.0.0 - ISC - -

      https://github.com/gr2m/universal-user-agent#readme

      -
      • Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      -
      +
      +        
      +
      +
    104. +
    105. +
      + universal-user-agent 6.0.0 - ISC +

      + https://github.com/gr2m/universal-user-agent#readme +

      +
        +
      • + Copyright (c) 2018, Gregor Martynus + (https://github.com/gr2m) +
      • +
      +
               # [ISC License](https://spdx.org/licenses/ISC)
       
       Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      @@ -1758,18 +1933,25 @@ 

      NOTICES AND INFORMATION

      Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    106. -
    107. -
      - - yallist 4.0.0 - ISC - -

      https://github.com/isaacs/yallist#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    108. +
    109. +
      + yallist 4.0.0 - ISC +

      + https://github.com/isaacs/yallist#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1785,18 +1967,24 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    110. -
    111. -
      - - @azure/abort-controller 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    112. +
    113. +
      + @azure/abort-controller 1.0.2 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1818,18 +2006,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    114. -
    115. -
      - - @azure/arm-cosmosdb 15.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    116. +
    117. +
      + @azure/arm-cosmosdb 15.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1850,18 +2044,24 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    118. -
    119. -
      - - @azure/arm-postgresql 6.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql

      -
      • Copyright (c) Microsoft Corporation.
      -
      +SOFTWARE.
      +        
      +
      +
    120. +
    121. +
      + @azure/arm-postgresql 6.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1882,18 +2082,26 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    122. -
    123. -
      - - @azure/arm-postgresql-flexible 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible

      -
      • Copyright (c) Microsoft Corporation.
      -
      +SOFTWARE.
      +        
      +
      +
    124. +
    125. +
      + + @azure/arm-postgresql-flexible 5.0.0 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -1937,18 +2145,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    126. -
    127. -
      - - @azure/arm-resources 4.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    128. +
    129. +
      + @azure/arm-resources 4.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1970,18 +2184,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    130. -
    131. -
      - - @azure/arm-resources 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    132. +
    133. +
      + @azure/arm-resources 5.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -2002,18 +2222,25 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    134. -
    135. -
      - - @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid

      - -
      +SOFTWARE.
      +        
      +
      +
    136. +
    137. +
      + + @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - + MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid +

      + +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2057,19 +2284,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    138. -
    139. -
      - - @azure/arm-resources-subscriptions 2.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions

      -
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    140. +
    141. +
      + + @azure/arm-resources-subscriptions 2.0.1 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions +

      +
        +
      • Copyright (c) 2022 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2090,19 +2325,25 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    142. -
    143. -
      - - @azure/arm-storage 18.2.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage

      -
      • Copyright (c) 2023 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +SOFTWARE.
      +        
      +
      +
    144. +
    145. +
      + @azure/arm-storage 18.2.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage +

      +
        +
      • Copyright (c) 2023 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2023 Microsoft
      @@ -2123,20 +2364,28 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    146. -
    147. -
      - - @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +SOFTWARE.
      +        
      +
      +
    148. +
    149. +
      + + @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) 2022 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2180,19 +2429,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    150. -
    151. -
      - - @azure/core-asynciterator-polyfill 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    152. +
    153. +
      + + @azure/core-asynciterator-polyfill 1.0.2 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2214,19 +2471,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    154. -
    155. -
      - - @azure/core-auth 1.5.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    156. +
    157. +
      + @azure/core-auth 1.5.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2248,20 +2511,29 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    158. -
    159. -
      - - @azure/core-client 1.7.3 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const CollectionFormatToDelimiterMap CSV
      -
      +
      +        
      +
      +
    160. +
    161. +
      + @azure/core-client 1.7.3 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) Microsoft Corporation. const + CollectionFormatToDelimiterMap CSV +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2283,19 +2555,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    162. -
    163. -
      - - @azure/core-lro 2.5.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    164. +
    165. +
      + @azure/core-lro 2.5.4 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2317,18 +2595,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    166. -
    167. -
      - - @azure/core-paging 1.2.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    168. +
    169. +
      + @azure/core-paging 1.2.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2350,20 +2634,29 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    170. -
    171. -
      - - @azure/core-rest-pipeline 1.12.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const RedactedString REDACTED Make
      -
      +
      +        
      +
      +
    172. +
    173. +
      + @azure/core-rest-pipeline 1.12.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) Microsoft Corporation. const + RedactedString REDACTED Make +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2385,19 +2678,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    174. -
    175. -
      - - @azure/core-tracing 1.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    176. +
    177. +
      + @azure/core-tracing 1.0.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2419,19 +2718,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    178. -
    179. -
      - - @azure/core-util 1.4.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    180. +
    181. +
      + @azure/core-util 1.4.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2453,19 +2758,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    182. -
    183. -
      - - @azure/cosmos 3.15.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) 2012-2015 Karan Lyons https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js
      -
      +
      +        
      +
      +
    184. +
    185. +
      + @azure/cosmos 3.15.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • + Copyright (c) 2012-2015 Karan Lyons + https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2487,19 +2801,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    186. -
    187. -
      - - @azure/logger 1.0.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    188. +
    189. +
      + @azure/logger 1.0.4 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2521,19 +2841,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    190. -
    191. -
      - - @azure/ms-rest-azure-js 2.1.0 - MIT - -

      https://github.com/Azure/ms-rest-azure-js

      -
      • Copyright (c) 2017
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    192. +
    193. +
      + @azure/ms-rest-azure-js 2.1.0 - MIT +

      + https://github.com/Azure/ms-rest-azure-js +

      +
        +
      • Copyright (c) 2017
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               MIT License
       
       Copyright (c) 2017 MIT
      @@ -2555,20 +2880,170 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    194. -
    195. -
      - - @azure/ms-rest-js 2.7.0 - MIT - -

      https://github.com/Azure/ms-rest-js

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      -
      +
      +        
      +
      +
    196. +
    197. +
      + @azure/ms-rest-js 2.7.0 - MIT +

      + https://github.com/Azure/ms-rest-js +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) 2010-2016 Robert Kieffer and other + contributors +
      • +
      +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation. All rights reserved.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    198. +
    199. +
      + @microsoft/1ds-core-js 3.2.3 - MIT +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • copyright Microsoft 2018
      • +
      • copyright Microsoft 2019
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • copyright Microsoft 2019 Simplified
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • + copyright Microsoft 2018 import AppInsightsCore as + InternalCore +
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    200. +
    201. +
      + @microsoft/1ds-post-js 3.2.3 - MIT +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • copyright Microsoft 2018
      • +
      • copyright Microsoft 2020
      • +
      • copyright Microsoft 2018-2020
      • +
      • copyright Microsoft 2022 Simple
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • + copyright Microsoft 2018-2020 import + IExtendedAppInsightsCore, SendRequestReason, + EventSendType +
      • +
      • + copyright Microsoft 2018-2020 import + IPerfManagerProvider, IValueSanitizer, + FieldValueSanitizerType, FieldValueSanitizerFunc, + SendRequestReason, EventSendType +
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    202. +
    203. +
      + + @microsoft/applicationinsights-core-js 2.8.4 - MIT + +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      +
                   MIT License
       
           Copyright (c) Microsoft Corporation. All rights reserved.
      @@ -2590,244 +3065,172 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - -
      -
      -
    204. -
    205. -
      - - @microsoft/1ds-core-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • copyright Microsoft 2018
      • -
      • copyright Microsoft 2019
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • copyright Microsoft 2019 Simplified
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018 import AppInsightsCore as InternalCore
      -
      -        Copyright (c) Microsoft Corporation.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -        
      -
      -
    206. -
    207. -
      - - @microsoft/1ds-post-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • copyright Microsoft 2018
      • -
      • copyright Microsoft 2020
      • -
      • copyright Microsoft 2018-2020
      • -
      • copyright Microsoft 2022 Simple
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018-2020 import IExtendedAppInsightsCore, SendRequestReason, EventSendType
      • -
      • copyright Microsoft 2018-2020 import IPerfManagerProvider, IValueSanitizer, FieldValueSanitizerType, FieldValueSanitizerFunc, SendRequestReason, EventSendType
      -
      -        Copyright (c) Microsoft Corporation.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -        
      -
      -
    208. -
    209. -
      - - @microsoft/applicationinsights-core-js 2.8.4 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation. All rights reserved.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    210. -
    211. -
      - - @microsoft/applicationinsights-shims 2.0.1 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Microsoft and contributors.
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation. All rights reserved.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    212. -
    213. -
      - - @microsoft/dynamicproto-js 1.1.6 - MIT - -

      https://github.com/microsoft/DynamicProto-JS#readme

      -
      • (c) James Halliday
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2012 Maximilian Antoni
      • -
      • Copyright (c) 2013 Maximilian Antoni
      • -
      • Copyright (c) 2020 Oliver Nightingale
      • -
      • Copyright (c) 2020 Oliver Nightingale A
      • -
      • Copyright (c) 2020 Oliver Nightingale An
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • Copyright (c) 2010-2013 Christian Johansen
      • -
      • Copyright (c) 2010-2014 Christian Johansen
      • -
      • Copyright (c) 2011 Sven Fuchs, Christian Johansen
      • -
      • Copyright Joyent, Inc. and other Node contributors
      • -
      • Copyright jQuery Foundation and other contributors
      • -
      • Copyright 2013 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
      • -
      • Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright 2006 Google Inc. https://code.google.com/p/google-diff-match-patch
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    214. -
    215. -
      - - @selderee/plugin-htmlparser2 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    216. -
    217. -
      - - @tootallnate/once 1.1.2 - MIT - -

      https://github.com/TooTallNate/once#readme

      - -
      +
      +        
      +
      +
    218. +
    219. +
      + + @microsoft/applicationinsights-shims 2.0.1 - MIT + +

      + https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • Copyright (c) Microsoft and contributors.
      • +
      +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation. All rights reserved.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    220. +
    221. +
      + @microsoft/dynamicproto-js 1.1.6 - MIT +

      + https://github.com/microsoft/DynamicProto-JS#readme +

      +
        +
      • (c) James Halliday
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) 2012 Maximilian Antoni
      • +
      • Copyright (c) 2013 Maximilian Antoni
      • +
      • Copyright (c) 2020 Oliver Nightingale
      • +
      • Copyright (c) 2020 Oliver Nightingale A
      • +
      • Copyright (c) 2020 Oliver Nightingale An
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • Copyright (c) 2010-2013 Christian Johansen
      • +
      • Copyright (c) 2010-2014 Christian Johansen
      • +
      • + Copyright (c) 2011 Sven Fuchs, Christian Johansen +
      • +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      • + Copyright jQuery Foundation and other contributors +
      • +
      • + Copyright 2013 jQuery Foundation, Inc. and other + contributors +
      • +
      • + Copyright (c) 2010-2014, Christian Johansen, + christian@cjohansen.no +
      • +
      • + Copyright 2005, 2014 jQuery Foundation, Inc. and + other contributors +
      • +
      • + Copyright 2006 Google Inc. + https://code.google.com/p/google-diff-match-patch +
      • +
      +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    222. +
    223. +
      + @selderee/plugin-htmlparser2 0.6.0 - MIT +

      + https://github.com/mxxii/selderee +

      + +
      +        MIT License
      +
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    224. +
    225. +
      + @tootallnate/once 1.1.2 - MIT +

      + https://github.com/TooTallNate/once#readme +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2836,18 +3239,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    226. -
    227. -
      - - @tootallnate/once 2.0.0 - MIT - -

      https://github.com/TooTallNate/once#readme

      -
      • Copyright (c) 2020 Nathan Rajlich
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    228. +
    229. +
      + @tootallnate/once 2.0.0 - MIT +

      + https://github.com/TooTallNate/once#readme +

      +
        +
      • Copyright (c) 2020 Nathan Rajlich
      • +
      +
               MIT License
       
       Copyright (c) 2020 Nathan Rajlich
      @@ -2869,18 +3277,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    230. -
    231. -
      - - @typescript-plus/fast-memoize-decorator 0.1.0 - MIT - - - -
      +
      +        
      +
      +
    232. +
    233. +
      + + @typescript-plus/fast-memoize-decorator 0.1.0 - MIT + + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2889,19 +3297,25 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    234. -
    235. -
      - - @vscode/extension-telemetry 0.6.2 - MIT - -

      https://github.com/Microsoft/vscode-extension-telemetry#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    236. +
    237. +
      + @vscode/extension-telemetry 0.6.2 - MIT +

      + https://github.com/Microsoft/vscode-extension-telemetry#readme +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      +
               vscode-extension-telemetry
       
       The MIT License (MIT)
      @@ -2924,18 +3338,19 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    238. -
    239. -
      - - 1to2 1.0.0 - MIT - - -
      • Copyright (c) 2014 3VOT
      -
      +SOFTWARE.
      +        
      +
      +
    240. +
    241. +
      + 1to2 1.0.0 - MIT + +
        +
      • Copyright (c) 2014 3VOT
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 3VOT
      @@ -2956,19 +3371,25 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    242. -
    243. -
      - - abort-controller 3.0.0 - MIT - -

      https://github.com/mysticatea/abort-controller#readme

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2017 Toru Nagashima
      -
      +
      +        
      +
      +
    244. +
    245. +
      + abort-controller 3.0.0 - MIT +

      + https://github.com/mysticatea/abort-controller#readme +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) 2017 Toru Nagashima
      • +
      +
               MIT License
       
       Copyright (c) 2017 Toru Nagashima
      @@ -2990,18 +3411,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    246. -
    247. -
      - - agent-base 6.0.2 - MIT - -

      https://github.com/TooTallNate/node-agent-base#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    248. +
    249. +
      + agent-base 6.0.2 - MIT +

      + https://github.com/TooTallNate/node-agent-base#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3010,18 +3440,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    250. -
    251. -
      - - async 3.2.3 - MIT - -

      https://caolan.github.io/async/

      -
      • Copyright (c) 2010-2018 Caolan McMahon
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    252. +
    253. +
      + async 3.2.3 - MIT +

      + https://caolan.github.io/async/ +

      +
        +
      • Copyright (c) 2010-2018 Caolan McMahon
      • +
      +
               Copyright (c) 2010-2018 Caolan McMahon
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3041,18 +3476,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    254. -
    255. -
      - - asynckit 0.4.0 - MIT - -

      https://github.com/alexindigo/asynckit#readme

      -
      • Copyright (c) 2016 Alex Indigo
      -
      +
      +        
      +
      +
    256. +
    257. +
      + asynckit 0.4.0 - MIT +

      + https://github.com/alexindigo/asynckit#readme +

      +
        +
      • Copyright (c) 2016 Alex Indigo
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Alex Indigo
      @@ -3074,18 +3514,21 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    258. -
    259. -
      - - axios 0.21.4 - MIT - -

      https://axios-http.com/

      - -
      +
      +        
      +
      +
    260. +
    261. +
      + axios 0.21.4 - MIT +

      + https://axios-http.com/ +

      + +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3105,18 +3548,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    262. -
    263. -
      - - axios 0.26.1 - MIT - -

      https://axios-http.com/

      -
      • Copyright (c) 2014-present Matt Zabriskie
      -
      +
      +        
      +
      +
    264. +
    265. +
      + axios 0.26.1 - MIT +

      + https://axios-http.com/ +

      +
        +
      • Copyright (c) 2014-present Matt Zabriskie
      • +
      +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3136,18 +3584,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    266. -
    267. -
      - - bl 2.2.1 - MIT - -

      https://github.com/rvagg/bl

      -
      • Copyright (c) 2013-2018 bl contributors
      -
      +
      +        
      +
      +
    268. +
    269. +
      + bl 2.2.1 - MIT +

      + https://github.com/rvagg/bl +

      +
        +
      • Copyright (c) 2013-2018 bl contributors
      • +
      +
               The MIT License (MIT)
       =====================
       
      @@ -3161,18 +3614,22 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    270. -
    271. -
      - - buffer-writer 2.0.0 - MIT - -

      https://github.com/brianc/node-buffer-writer#readme

      - -
      +
      +        
      +
      +
    272. +
    273. +
      + buffer-writer 2.0.0 - MIT +

      + https://github.com/brianc/node-buffer-writer#readme +

      + +
               The MIT License (MIT)
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3192,18 +3649,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    274. -
    275. -
      - - combined-stream 1.0.8 - MIT - -

      https://github.com/felixge/node-combined-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +
      +        
      +
      +
    276. +
    277. +
      + combined-stream 1.0.8 - MIT +

      + https://github.com/felixge/node-combined-stream +

      +
        +
      • + Copyright (c) 2011 Debuggable Limited + <felix@debuggable.com> +
      • +
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3223,18 +3689,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    278. -
    279. -
      - - commander 2.20.3 - MIT - -

      https://github.com/tj/commander.js#readme

      -
      • Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      -
      +
      +        
      +
      +
    280. +
    281. +
      + commander 2.20.3 - MIT +

      + https://github.com/tj/commander.js#readme +

      +
        +
      • + Copyright (c) 2011 TJ Holowaychuk + <tj@vision-media.ca> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3257,18 +3731,25 @@ 

      NOTICES AND INFORMATION

      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    282. -
    283. -
      - - core-util-is 1.0.2 - MIT - -

      https://github.com/isaacs/core-util-is#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    284. +
    285. +
      + core-util-is 1.0.2 - MIT +

      + https://github.com/isaacs/core-util-is#readme +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Copyright Node.js contributors. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3288,18 +3769,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    286. -
    287. -
      - - dayjs 1.11.2 - MIT - -

      https://day.js.org/

      -
      • Copyright (c) 2018-present, iamkun
      -
      +
      +        
      +
      +
    288. +
    289. +
      + dayjs 1.11.2 - MIT +

      https://day.js.org/

      +
        +
      • Copyright (c) 2018-present, iamkun
      • +
      +
               MIT License
       
       Copyright (c) 2018-present, iamkun
      @@ -3321,19 +3803,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    290. -
    291. -
      - - debug 4.3.4 - MIT - -

      https://github.com/debug-js/debug#readme

      -
      • Copyright (c) 2018-2021 Josh Junon
      • -
      • Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      -
      +
      +        
      +
      +
    292. +
    293. +
      + debug 4.3.4 - MIT +

      + https://github.com/debug-js/debug#readme +

      +
        +
      • Copyright (c) 2018-2021 Josh Junon
      • +
      • + Copyright (c) 2014-2017 TJ Holowaychuk + <tj@vision-media.ca> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3354,18 +3844,26 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    294. -
    295. -
      - - deepmerge 4.2.2 - MIT - -

      https://github.com/TehShrike/deepmerge

      -
      • Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      -
      +
      +        
      +
      +
    296. +
    297. +
      + deepmerge 4.2.2 - MIT +

      + https://github.com/TehShrike/deepmerge +

      +
        +
      • + Copyright (c) 2012 James Halliday, Josh Duff, and + other contributors +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      @@ -3387,19 +3885,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    298. -
    299. -
      - - define-lazy-prop 2.0.0 - MIT - -

      https://github.com/sindresorhus/define-lazy-prop#readme

      -
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +
      +        
      +
      +
    300. +
    301. +
      + define-lazy-prop 2.0.0 - MIT +

      + https://github.com/sindresorhus/define-lazy-prop#readme +

      +
        +
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3409,18 +3916,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    302. -
    303. -
      - - delayed-stream 1.0.0 - MIT - -

      https://github.com/felixge/node-delayed-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +
      +        
      +
      +
    304. +
    305. +
      + delayed-stream 1.0.0 - MIT +

      + https://github.com/felixge/node-delayed-stream +

      +
        +
      • + Copyright (c) 2011 Debuggable Limited + <felix@debuggable.com> +
      • +
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3440,18 +3955,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    306. -
    307. -
      - - discontinuous-range 1.0.0 - MIT - -

      https://github.com/dtudury/discontinuous-range

      -
      • Copyright (c) 2014 David Tudury
      -
      +
      +        
      +
      +
    308. +
    309. +
      + discontinuous-range 1.0.0 - MIT +

      + https://github.com/dtudury/discontinuous-range +

      +
        +
      • Copyright (c) 2014 David Tudury
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 David Tudury
      @@ -3473,18 +3993,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    310. -
    311. -
      - - dom-serializer 1.4.1 - MIT - -

      https://github.com/cheeriojs/dom-renderer#readme

      -
      • Copyright (c) 2014 The cheeriojs contributors
      -
      +
      +        
      +
      +
    312. +
    313. +
      + dom-serializer 1.4.1 - MIT +

      + https://github.com/cheeriojs/dom-renderer#readme +

      +
        +
      • Copyright (c) 2014 The cheeriojs contributors
      • +
      +
               License
       
       (The MIT License)
      @@ -3496,18 +4022,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    314. -
    315. -
      - - duplexer 0.1.1 - MIT - -

      https://github.com/Raynos/duplexer

      -
      • Copyright (c) 2012 Raynos.
      -
      +
      +        
      +
      +
    316. +
    317. +
      + duplexer 0.1.1 - MIT +

      + https://github.com/Raynos/duplexer +

      +
        +
      • Copyright (c) 2012 Raynos.
      • +
      +
               Copyright (c) 2012 Raynos.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3526,19 +4057,28 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -
      -
      -
    318. -
    319. -
      - - escape-string-regexp 2.0.0 - MIT - -

      https://github.com/sindresorhus/escape-string-regexp#readme

      -
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +THE SOFTWARE.
      +        
      +
      +
    320. +
    321. +
      + escape-string-regexp 2.0.0 - MIT +

      + https://github.com/sindresorhus/escape-string-regexp#readme +

      +
        +
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3548,18 +4088,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    322. -
    323. -
      - - event-stream 4.0.1 - MIT - -

      http://github.com/dominictarr/event-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    324. +
    325. +
      + event-stream 4.0.1 - MIT +

      + http://github.com/dominictarr/event-stream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3584,19 +4129,25 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    326. -
    327. -
      - - event-target-shim 5.0.1 - MIT - -

      https://github.com/mysticatea/event-target-shim

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2015 Toru Nagashima
      -
      +
      +        
      +
      +
    328. +
    329. +
      + event-target-shim 5.0.1 - MIT +

      + https://github.com/mysticatea/event-target-shim +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) 2015 Toru Nagashima
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2015 Toru Nagashima
      @@ -3619,19 +4170,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    330. -
    331. -
      - - fast-json-stable-stringify 2.1.0 - MIT - -

      https://github.com/epoberezkin/fast-json-stable-stringify

      -
      • Copyright (c) 2013 James Halliday
      • -
      • Copyright (c) 2017 Evgeny Poberezkin
      -
      +
      +        
      +
      +
    332. +
    333. +
      + fast-json-stable-stringify 2.1.0 - MIT +

      + https://github.com/epoberezkin/fast-json-stable-stringify +

      +
        +
      • Copyright (c) 2013 James Halliday
      • +
      • Copyright (c) 2017 Evgeny Poberezkin
      • +
      +
               This software is released under the MIT license:
       
       Copyright (c) 2017 Evgeny Poberezkin
      @@ -3653,18 +4210,24 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    334. -
    335. -
      - - fast-memoize 2.5.2 - MIT - -

      https://github.com/caiogondim/fast-memoize#readme

      -
      • Copyright (c) 2016 Caio Gondim
      -
      +
      +        
      +
      +
    336. +
    337. +
      + fast-memoize 2.5.2 - MIT +

      + https://github.com/caiogondim/fast-memoize#readme +

      +
        +
      • Copyright (c) 2016 Caio Gondim
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Caio Gondim
      @@ -3686,18 +4249,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    338. -
    339. -
      - - follow-redirects 1.14.8 - MIT - -

      https://github.com/follow-redirects/follow-redirects

      -
      • Copyright 2014-present Olivier Lalonde <olalonde@gmail.com> , James Talmage <james@talmage.io> , Ruben Verborgh
      -
      +
      +        
      +
      +
    340. +
    341. +
      + follow-redirects 1.14.8 - MIT +

      + https://github.com/follow-redirects/follow-redirects +

      +
        +
      • + Copyright 2014-present Olivier Lalonde + <olalonde@gmail.com> , James Talmage + <james@talmage.io> , Ruben Verborgh +
      • +
      +
               Copyright 2014–present Olivier Lalonde <olalonde@gmail.com>, James Talmage <james@talmage.io>, Ruben Verborgh
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of
      @@ -3716,18 +4289,26 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    342. -
    343. -
      - - form-data 2.5.1 - MIT - -

      https://github.com/form-data/form-data#readme

      -
      • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
      -
      +
      +        
      +
      +
    344. +
    345. +
      + form-data 2.5.1 - MIT +

      + https://github.com/form-data/form-data#readme +

      +
        +
      • + Copyright (c) 2012 Felix Geisendorfer + (felix@debuggable.com) and contributors +
      • +
      +
               Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
       
        Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3747,18 +4328,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    346. -
    347. -
      - - form-data 4.0.0 - MIT - -

      https://github.com/form-data/form-data#readme

      -
      • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
      -
      +
      +        
      +
      +
    348. +
    349. +
      + form-data 4.0.0 - MIT +

      + https://github.com/form-data/form-data#readme +

      +
        +
      • + Copyright (c) 2012 Felix Geisendorfer + (felix@debuggable.com) and contributors +
      • +
      +
               Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
       
        Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3778,18 +4367,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    350. -
    351. -
      - - from 0.1.7 - MIT - -

      https://github.com/dominictarr/from#readme

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    352. +
    353. +
      + from 0.1.7 - MIT +

      + https://github.com/dominictarr/from#readme +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3814,20 +4408,31 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    354. -
    355. -
      - - fs-extra 8.1.0 - MIT - -

      https://github.com/jprichardson/node-fs-extra

      -
      • Copyright (c) 2011-2017 JP Richardson
      • -
      • Copyright (c) 2011-2017 JP Richardson (https://github.com/jprichardson)
      • -
      • Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
      -
      +
      +        
      +
      +
    356. +
    357. +
      + fs-extra 8.1.0 - MIT +

      + https://github.com/jprichardson/node-fs-extra +

      +
        +
      • Copyright (c) 2011-2017 JP Richardson
      • +
      • + Copyright (c) 2011-2017 JP Richardson + (https://github.com/jprichardson) +
      • +
      • + Copyright (c) 2014-2016 Jonathan Ong + me@jongleberry.com and Contributors +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2011-2017 JP Richardson
      @@ -3843,18 +4448,22 @@ 

      NOTICES AND INFORMATION

      WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    358. -
    359. -
      - - he 1.2.0 - MIT - -

      https://mths.be/he

      -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +
      +        
      +
      +
    360. +
    361. +
      + he 1.2.0 - MIT +

      https://mths.be/he

      +
        +
      • + Copyright Mathias Bynens + <https://mathiasbynens.be/> +
      • +
      +
               Copyright Mathias Bynens <https://mathiasbynens.be/>
       
       Permission is hereby granted, free of charge, to any person obtaining
      @@ -3875,18 +4484,26 @@ 

      NOTICES AND INFORMATION

      LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    362. -
    363. -
      - - htmlparser2 6.1.0 - MIT - -

      https://github.com/fb55/htmlparser2#readme

      -
      • Copyright 2010, 2011, Chris Winberry <chris@winberry.net>
      -
      +
      +        
      +
      +
    364. +
    365. +
      + htmlparser2 6.1.0 - MIT +

      + https://github.com/fb55/htmlparser2#readme +

      +
        +
      • + Copyright 2010, 2011, Chris Winberry + <chris@winberry.net> +
      • +
      +
               Copyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.
       Permission is hereby granted, free of charge, to any person obtaining a copy
       of this software and associated documentation files (the "Software"), to
      @@ -3904,19 +4521,31 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -
      -
      -
    366. -
    367. -
      - - html-to-text 8.2.0 - MIT - -

      https://github.com/html-to-text/node-html-to-text

      -
      • Portions Copyright (c) 2020 KillyMXI <killy@mxii.eu.org>
      • -
      • Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
      -
      +IN THE SOFTWARE.
      +        
      +
      +
    368. +
    369. +
      + html-to-text 8.2.0 - MIT +

      + https://github.com/html-to-text/node-html-to-text +

      +
        +
      • + Portions Copyright (c) 2020 KillyMXI + <killy@mxii.eu.org> +
      • +
      • + Portions Copyright (c) 2012-2019 werk85 + <malte@werk85.de> +
      • +
      +
               MIT License
       
       Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
      @@ -3942,18 +4571,27 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    370. -
    371. -
      - - http-proxy-agent 4.0.1 - MIT - -

      https://github.com/TooTallNate/node-http-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    372. +
    373. +
      + http-proxy-agent 4.0.1 - MIT +

      + https://github.com/TooTallNate/node-http-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3962,18 +4600,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    374. -
    375. -
      - - http-proxy-agent 5.0.0 - MIT - -

      https://github.com/TooTallNate/node-http-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    376. +
    377. +
      + http-proxy-agent 5.0.0 - MIT +

      + https://github.com/TooTallNate/node-http-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3982,18 +4629,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    378. -
    379. -
      - - https-proxy-agent 5.0.0 - MIT - -

      https://github.com/TooTallNate/node-https-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    380. +
    381. +
      + https-proxy-agent 5.0.0 - MIT +

      + https://github.com/TooTallNate/node-https-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4002,18 +4658,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    382. -
    383. -
      - - indexable-array 0.7.0 - MIT - -

      https://github.com/ozum/indexable-array

      -
      • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    384. +
    385. +
      + indexable-array 0.7.0 - MIT +

      + https://github.com/ozum/indexable-array +

      +
        +
      • + Copyright (c) 2021 Ozum Eldogan + <ozum@ozum.net> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net>
      @@ -4035,19 +4699,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    386. -
    387. -
      - - inflection 1.12.0 - MIT - -

      https://github.com/dreamerslab/node.inflection#readme

      -
      • Copyright (c) 2011
      • -
      • Copyright (c) 2011 Ben Lin <ben@dreamerslab.com>
      -
      +
      +        
      +
      +
    388. +
    389. +
      + inflection 1.12.0 - MIT +

      + https://github.com/dreamerslab/node.inflection#readme +

      +
        +
      • Copyright (c) 2011
      • +
      • + Copyright (c) 2011 Ben Lin + <ben@dreamerslab.com> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4056,18 +4729,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    390. -
    391. -
      - - isarray 1.0.0 - MIT - -

      https://github.com/juliangruber/isarray

      -
      • Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    392. +
    393. +
      + isarray 1.0.0 - MIT +

      + https://github.com/juliangruber/isarray +

      +
        +
      • + Copyright (c) 2013 Julian Gruber + <julian@juliangruber.com> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4076,18 +4757,28 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    394. -
    395. -
      - - is-docker 2.2.1 - MIT - -

      https://github.com/sindresorhus/is-docker#readme

      -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    396. +
    397. +
      + is-docker 2.2.1 - MIT +

      + https://github.com/sindresorhus/is-docker#readme +

      +
        +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> + (https://sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      @@ -4097,18 +4788,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    398. -
    399. -
      - - is-wsl 2.2.0 - MIT - -

      https://github.com/sindresorhus/is-wsl#readme

      -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +
      +        
      +
      +
    400. +
    401. +
      + is-wsl 2.2.0 - MIT +

      + https://github.com/sindresorhus/is-wsl#readme +

      +
        +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -4118,20 +4817,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    402. -
    403. -
      - - json5 2.2.3 - MIT - -

      http://json5.org/

      -
      • (c) 2019 Denis Pushkarev
      • -
      • copyright (c) 2019 Denis Pushkarev
      • -
      • Copyright (c) 2012-2018 Aseem Kishore, and others
      -
      +
      +        
      +
      +
    404. +
    405. +
      + json5 2.2.3 - MIT +

      http://json5.org/

      +
        +
      • (c) 2019 Denis Pushkarev
      • +
      • copyright (c) 2019 Denis Pushkarev
      • +
      • + Copyright (c) 2012-2018 Aseem Kishore, and others +
      • +
      +
               MIT License
       
       Copyright (c) 2012-2018 Aseem Kishore, and [others].
      @@ -4155,54 +4857,72 @@ 

      NOTICES AND INFORMATION

      SOFTWARE. [others]: https://github.com/json5/json5/contributors - -
      -
      -
    406. -
    407. -
      - - jsonc-parser 2.2.1 - MIT - -

      https://github.com/microsoft/node-jsonc-parser#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright 2018, Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      -        The MIT License (MIT)
      -
      -Copyright (c) Microsoft
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    408. -
    409. -
      - - jsonfile 4.0.0 - MIT - -

      https://github.com/jprichardson/node-jsonfile#readme

      -
      • Copyright 2012-2016, JP Richardson <jprichardson@gmail.com>
      • -
      • Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
      -
      +
      +        
      +
      +
    410. +
    411. +
      + jsonc-parser 2.2.1 - MIT +

      + https://github.com/microsoft/node-jsonc-parser#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright 2018, Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) Microsoft
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    412. +
    413. +
      + jsonfile 4.0.0 - MIT +

      + https://github.com/jprichardson/node-jsonfile#readme +

      +
        +
      • + Copyright 2012-2016, JP Richardson + <jprichardson@gmail.com> +
      • +
      • + Copyright (c) 2012-2015, JP Richardson + <jprichardson@gmail.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
      @@ -4218,19 +4938,24 @@ 

      NOTICES AND INFORMATION

      WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    414. -
    415. -
      - - jsonparse 1.3.1 - MIT - -

      https://github.com/creationix/jsonparse#readme

      -
      • Copyright (c) 2012 Tim Caswell
      • -
      • Copyright (c) 2011-2012 Tim Caswell
      -
      +
      +        
      +
      +
    416. +
    417. +
      + jsonparse 1.3.1 - MIT +

      + https://github.com/creationix/jsonparse#readme +

      +
        +
      • Copyright (c) 2012 Tim Caswell
      • +
      • Copyright (c) 2011-2012 Tim Caswell
      • +
      +
               The MIT License
       
       Copyright (c) 2012 Tim Caswell
      @@ -4255,20 +4980,31 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    418. -
    419. -
      - - lodash.get 4.4.2 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    420. +
    421. +
      + lodash.get 4.4.2 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4316,20 +5052,31 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    422. -
    423. -
      - - lodash.isfunction 3.0.9 - MIT - -

      https://lodash.com/

      -
      • Copyright JS Foundation and other contributors <https://js.foundation/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    424. +
    425. +
      + lodash.isfunction 3.0.9 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright JS Foundation and other contributors + <https://js.foundation/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright JS Foundation and other contributors <https://js.foundation/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4377,20 +5124,31 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    426. -
    427. -
      - - lodash.set 4.3.2 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    428. +
    429. +
      + lodash.set 4.3.2 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4438,20 +5196,31 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    430. -
    431. -
      - - lodash.transform 4.6.0 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    432. +
    433. +
      + lodash.transform 4.6.0 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4499,18 +5268,23 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    434. -
    435. -
      - - map-stream 0.0.7 - MIT - -

      http://github.com/dominictarr/map-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    436. +
    437. +
      + map-stream 0.0.7 - MIT +

      + http://github.com/dominictarr/map-stream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -4535,18 +5309,23 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    438. -
    439. -
      - - memory-pager 1.5.0 - MIT - -

      https://github.com/mafintosh/memory-pager

      -
      • Copyright (c) 2017 Mathias Buus
      -
      +
      +        
      +
      +
    440. +
    441. +
      + memory-pager 1.5.0 - MIT +

      + https://github.com/mafintosh/memory-pager +

      +
        +
      • Copyright (c) 2017 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2017 Mathias Buus
      @@ -4568,19 +5347,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    442. -
    443. -
      - - mime-db 1.44.0 - MIT - -

      https://github.com/jshttp/mime-db#readme

      -
      • Copyright (c) 2014 Jonathan Ong
      • -
      • Copyright (c) 2014 Jonathan Ong me@jongleberry.com
      -
      +
      +        
      +
      +
    444. +
    445. +
      + mime-db 1.44.0 - MIT +

      + https://github.com/jshttp/mime-db#readme +

      +
        +
      • Copyright (c) 2014 Jonathan Ong
      • +
      • + Copyright (c) 2014 Jonathan Ong me@jongleberry.com +
      • +
      +
               
       The MIT License (MIT)
       
      @@ -4603,21 +5389,32 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    446. -
    447. -
      - - mime-types 2.1.27 - MIT - -

      https://github.com/jshttp/mime-types#readme

      -
      • Copyright (c) 2014 Jonathan Ong
      • -
      • Copyright (c) 2015 Douglas Christopher Wilson
      • -
      • Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
      • -
      • Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
      -
      +
      +        
      +
      +
    448. +
    449. +
      + mime-types 2.1.27 - MIT +

      + https://github.com/jshttp/mime-types#readme +

      +
        +
      • Copyright (c) 2014 Jonathan Ong
      • +
      • Copyright (c) 2015 Douglas Christopher Wilson
      • +
      • + Copyright (c) 2014 Jonathan Ong + <me@jongleberry.com> +
      • +
      • + Copyright (c) 2015 Douglas Christopher Wilson + <doug@somethingdoug.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
      @@ -4641,18 +5438,21 @@ 

      NOTICES AND INFORMATION

      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    450. -
    451. -
      - - minimist 1.2.6 - MIT - -

      https://github.com/substack/minimist

      - -
      +
      +        
      +
      +
    452. +
    453. +
      + minimist 1.2.6 - MIT +

      + https://github.com/substack/minimist +

      + +
               This software is released under the MIT license:
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of
      @@ -4671,18 +5471,25 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    454. -
    455. -
      - - moment 2.29.4 - MIT - -

      https://momentjs.com/

      -
      • Copyright (c) JS Foundation and other contributors
      -
      +
      +        
      +
      +
    456. +
    457. +
      + moment 2.29.4 - MIT +

      + https://momentjs.com/ +

      +
        +
      • + Copyright (c) JS Foundation and other contributors +
      • +
      +
               Copyright (c) JS Foundation and other contributors
       
       Permission is hereby granted, free of charge, to any person
      @@ -4705,18 +5512,23 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    458. -
    459. -
      - - ms 2.1.2 - MIT - -

      https://github.com/zeit/ms#readme

      -
      • Copyright (c) 2016 Zeit, Inc.
      -
      +
      +        
      +
      +
    460. +
    461. +
      + ms 2.1.2 - MIT +

      + https://github.com/zeit/ms#readme +

      +
        +
      • Copyright (c) 2016 Zeit, Inc.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Zeit, Inc.
      @@ -4738,18 +5550,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    462. -
    463. -
      - - nearley 2.20.1 - MIT - -

      https://github.com/hardmath123/nearley#readme

      -
      • Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
      -
      +
      +        
      +
      +
    464. +
    465. +
      + nearley 2.20.1 - MIT +

      + https://github.com/hardmath123/nearley#readme +

      +
        +
      • + Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 + Kartik Chandra, Tim Radvan +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
      @@ -4771,18 +5591,22 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    466. -
    467. -
      - - node-abort-controller 3.0.1 - MIT - -

      https://github.com/southpolesteve/node-abort-controller#readme

      - -
      +
      +        
      +
      +
    468. +
    469. +
      + node-abort-controller 3.0.1 - MIT +

      + https://github.com/southpolesteve/node-abort-controller#readme +

      + +
               MIT License
       
       Copyright (c) 2019 Steve Faulkner
      @@ -4804,18 +5628,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    470. -
    471. -
      - - node-fetch 2.6.7 - MIT - -

      https://github.com/bitinn/node-fetch

      -
      • Copyright (c) 2016 David Frank
      -
      +
      +        
      +
      +
    472. +
    473. +
      + node-fetch 2.6.7 - MIT +

      + https://github.com/bitinn/node-fetch +

      +
        +
      • Copyright (c) 2016 David Frank
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 David Frank
      @@ -4838,22 +5667,43 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    474. -
    475. -
      - - open 8.4.2 - MIT - -

      https://github.com/sindresorhus/open#readme

      -
      • Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
      • -
      • Copyright 2006, Jeremy White <jwhite@codeweavers.com>
      • -
      • Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
      • -
      • Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      -
      +
      +        
      +
      +
    476. +
    477. +
      + open 8.4.2 - MIT +

      + https://github.com/sindresorhus/open#readme +

      +
        +
      • + Copyright 2006, Kevin Krammer + <kevin.krammer@gmx.at> +
      • +
      • + Copyright 2006, Jeremy White + <jwhite@codeweavers.com> +
      • +
      • + Copyright 2009-2010, Fathi Boudra + <fabo@freedesktop.org> +
      • +
      • + Copyright 2009-2010, Rex Dieter + <rdieter@fedoraproject.org> +
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> + (https://sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      @@ -4863,18 +5713,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    478. -
    479. -
      - - packet-reader 1.0.0 - MIT - -

      https://github.com/brianc/node-packet-reader

      -
      • Copyright 2015 Brian M. Carlson
      -
      +
      +        
      +
      +
    480. +
    481. +
      + packet-reader 1.0.0 - MIT +

      + https://github.com/brianc/node-packet-reader +

      +
        +
      • Copyright 2015 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4883,71 +5738,87 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    482. -
    483. -
      - - parseley 0.7.0 - MIT - -

      https://github.com/mxxii/parseley

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    484. -
    485. -
      - - performance-now 2.1.0 - MIT - -

      https://github.com/braveg1rl/performance-now

      -
      • Copyright (c) 2013 Braveg1rl
      • -
      • Copyright (c) 2017 Braveg1rl
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    486. +
    487. +
      + parseley 0.7.0 - MIT +

      + https://github.com/mxxii/parseley +

      + +
      +        MIT License
      +
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    488. +
    489. +
      + performance-now 2.1.0 - MIT +

      + https://github.com/braveg1rl/performance-now +

      +
        +
      • Copyright (c) 2013 Braveg1rl
      • +
      • Copyright (c) 2017 Braveg1rl
      • +
      +
               Copyright (c) 2013 Braveg1rl
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
       
       The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
       
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -        
      -
      -
    490. -
    491. -
      - - pg 8.11.2 - MIT - -

      https://github.com/brianc/node-postgres

      -
      • Copyright (c) 2010 - 2021 Brian Carlson
      • -
      • Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    492. +
    493. +
      + pg 8.11.2 - MIT +

      + https://github.com/brianc/node-postgres +

      +
        +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      • + Copyright (c) 2010-2020 Brian Carlson + (brian.m.carlson@gmail.com) +
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -4969,19 +5840,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    494. -
    495. -
      - - pg-cloudflare 1.1.1 - MIT - -

      https://github.com/brianc/node-postgres#readme

      -
      • Copyright (c) 2023 Brian M. Carlson
      • -
      • Copyright (c) 2010 - 2021 Brian Carlson
      -
      +
      +        
      +
      +
    496. +
    497. +
      + pg-cloudflare 1.1.1 - MIT +

      + https://github.com/brianc/node-postgres#readme +

      +
        +
      • Copyright (c) 2023 Brian M. Carlson
      • +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -5003,19 +5879,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    498. -
    499. -
      - - pg-connection-string 2.6.2 - MIT - -

      https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string

      -
      • Copyright (c) 2014 Iced Development
      • -
      • Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
      -
      +
      +        
      +
      +
    500. +
    501. +
      + pg-connection-string 2.6.2 - MIT +

      + https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string +

      +
        +
      • Copyright (c) 2014 Iced Development
      • +
      • + Copyright (c) 2010-2014 Brian Carlson + (brian.m.carlson@gmail.com) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 Iced Development
      @@ -5036,18 +5921,23 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    502. -
    503. -
      - - pgpass 1.0.2 - MIT - -

      https://github.com/hoegaarden/pgpass#readme

      -
      • Copyright (c) 2013-2016 Hannes Horl
      -
      +SOFTWARE.
      +        
      +
      +
    504. +
    505. +
      + pgpass 1.0.2 - MIT +

      + https://github.com/hoegaarden/pgpass#readme +

      +
        +
      • Copyright (c) 2013-2016 Hannes Horl
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5056,19 +5946,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    506. -
    507. -
      - - pg-pool 3.6.1 - MIT - -

      https://github.com/brianc/node-pg-pool#readme

      -
      • Copyright (c) 2016 Brian M. Carlson
      • -
      • Copyright (c) 2017 Brian M. Carlson
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    508. +
    509. +
      + pg-pool 3.6.1 - MIT +

      + https://github.com/brianc/node-pg-pool#readme +

      +
        +
      • Copyright (c) 2016 Brian M. Carlson
      • +
      • Copyright (c) 2017 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2017 Brian M. Carlson
      @@ -5090,18 +5985,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    510. -
    511. -
      - - pg-protocol 1.6.0 - MIT - -

      https://github.com/brianc/node-postgres#readme

      -
      • Copyright (c) 2010 - 2021 Brian Carlson
      -
      +
      +        
      +
      +
    512. +
    513. +
      + pg-protocol 1.6.0 - MIT +

      + https://github.com/brianc/node-postgres#readme +

      +
        +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -5123,18 +6023,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    514. -
    515. -
      - - pg-structure 7.15.0 - MIT - -

      https://www.pg-structure.com/

      -
      • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net> (https://www.ozum.net/)
      -
      +
      +        
      +
      +
    516. +
    517. +
      + pg-structure 7.15.0 - MIT +

      + https://www.pg-structure.com/ +

      +
        +
      • + Copyright (c) 2021 Ozum Eldogan + <ozum@ozum.net> (https://www.ozum.net/) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net> (https://www.ozum.net/)
      @@ -5156,18 +6064,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    518. -
    519. -
      - - pg-types 2.2.0 - MIT - -

      https://github.com/brianc/node-pg-types

      -
      • Copyright (c) 2014 Brian M. Carlson
      -
      +
      +        
      +
      +
    520. +
    521. +
      + pg-types 2.2.0 - MIT +

      + https://github.com/brianc/node-pg-types +

      +
        +
      • Copyright (c) 2014 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5176,19 +6089,28 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    522. -
    523. -
      - - postgres-array 2.0.0 - MIT - -

      https://github.com/bendrucker/postgres-array#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    524. +
    525. +
      + postgres-array 2.0.0 - MIT +

      + https://github.com/bendrucker/postgres-array#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5210,19 +6132,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    526. -
    527. -
      - - postgres-bytea 1.0.0 - MIT - -

      https://github.com/bendrucker/postgres-bytea#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +
      +        
      +
      +
    528. +
    529. +
      + postgres-bytea 1.0.0 - MIT +

      + https://github.com/bendrucker/postgres-bytea#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5244,19 +6175,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    530. -
    531. -
      - - postgres-date 1.0.6 - MIT - -

      https://github.com/bendrucker/postgres-date#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +
      +        
      +
      +
    532. +
    533. +
      + postgres-date 1.0.6 - MIT +

      + https://github.com/bendrucker/postgres-date#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5278,19 +6218,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    534. -
    535. -
      - - postgres-interval 1.2.0 - MIT - -

      https://github.com/bendrucker/postgres-interval#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +
      +        
      +
      +
    536. +
    537. +
      + postgres-interval 1.2.0 - MIT +

      + https://github.com/bendrucker/postgres-interval#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5312,18 +6261,22 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    538. -
    539. -
      - - priorityqueuejs 1.0.0 - MIT - -

      https://github.com/janogonzalez/priorityqueuejs

      - -
      +
      +        
      +
      +
    540. +
    541. +
      + priorityqueuejs 1.0.0 - MIT +

      + https://github.com/janogonzalez/priorityqueuejs +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5332,18 +6285,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    542. -
    543. -
      - - process-nextick-args 2.0.1 - MIT - -

      https://github.com/calvinmetcalf/process-nextick-args

      -
      • Copyright (c) 2015 Calvin Metcalf
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    544. +
    545. +
      + process-nextick-args 2.0.1 - MIT +

      + https://github.com/calvinmetcalf/process-nextick-args +

      +
        +
      • Copyright (c) 2015 Calvin Metcalf
      • +
      +
               # Copyright (c) 2015 Calvin Metcalf
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5363,18 +6322,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** - -
      -
      -
    546. -
    547. -
      - - raf 3.4.1 - MIT - -

      https://github.com/chrisdickinson/raf#readme

      -
      • Copyright 2013 Chris Dickinson <chris@neversaw.us>
      -
      +
      +        
      +
      +
    548. +
    549. +
      + raf 3.4.1 - MIT +

      + https://github.com/chrisdickinson/raf#readme +

      +
        +
      • + Copyright 2013 Chris Dickinson + <chris@neversaw.us> +
      • +
      +
               Copyright 2013 Chris Dickinson <chris@neversaw.us>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      @@ -5382,18 +6349,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    550. -
    551. -
      - - randexp 0.4.6 - MIT - -

      http://fent.github.io/randexp.js/

      -
      • Copyright (c) 2011 by Roly Fentanes
      -
      +
      +        
      +
      +
    552. +
    553. +
      + randexp 0.4.6 - MIT +

      + http://fent.github.io/randexp.js/ +

      +
        +
      • Copyright (c) 2011 by Roly Fentanes
      • +
      +
               Copyright (C) 2011 by Roly Fentanes
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5413,18 +6385,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    554. -
    555. -
      - - readable-stream 2.3.7 - MIT - -

      https://github.com/nodejs/readable-stream#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    556. +
    557. +
      + readable-stream 2.3.7 - MIT +

      + https://github.com/nodejs/readable-stream#readme +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Node.js is licensed for use as follows:
       
       """
      @@ -5472,18 +6452,23 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - -
      -
      -
    558. -
    559. -
      - - ret 0.1.15 - MIT - -

      https://github.com/fent/ret.js#readme

      -
      • Copyright (c) 2011 by Roly Fentanes
      -
      +
      +        
      +
      +
    560. +
    561. +
      + ret 0.1.15 - MIT +

      + https://github.com/fent/ret.js#readme +

      +
        +
      • Copyright (c) 2011 by Roly Fentanes
      • +
      +
               Copyright (C) 2011 by Roly Fentanes
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5503,19 +6488,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    562. -
    563. -
      - - safe-buffer 5.1.2 - MIT - -

      https://github.com/feross/safe-buffer

      -
      • Copyright (c) Feross Aboukhadijeh
      • -
      • Copyright (c) Feross Aboukhadijeh (http://feross.org)
      -
      +
      +        
      +
      +
    564. +
    565. +
      + safe-buffer 5.1.2 - MIT +

      + https://github.com/feross/safe-buffer +

      +
        +
      • Copyright (c) Feross Aboukhadijeh
      • +
      • + Copyright (c) Feross Aboukhadijeh + (http://feross.org) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Feross Aboukhadijeh
      @@ -5537,19 +6530,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    566. -
    567. -
      - - saslprep 1.0.3 - MIT - -

      https://github.com/reklatsmasters/saslprep#readme

      -
      • (c) Dmitriy Tsvettsikh
      • -
      • Copyright (c) 2014 Dmitry Tsvettsikh
      -
      +
      +        
      +
      +
    568. +
    569. +
      + saslprep 1.0.3 - MIT +

      + https://github.com/reklatsmasters/saslprep#readme +

      +
        +
      • (c) Dmitriy Tsvettsikh
      • +
      • Copyright (c) 2014 Dmitry Tsvettsikh
      • +
      +
               Copyright (c) 2014 Dmitry Tsvettsikh
       
       Permission is hereby granted, free of charge, to any person
      @@ -5571,51 +6570,57 @@ 

      NOTICES AND INFORMATION

      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    570. -
    571. -
      - - selderee 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    572. -
    573. -
      - - semaphore 1.0.5 - MIT - -

      https://github.com/abrkn/semaphore.js

      - -
      +OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    574. +
    575. +
      + selderee 0.6.0 - MIT +

      + https://github.com/mxxii/selderee +

      + +
      +        MIT License
      +
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    576. +
    577. +
      + semaphore 1.0.5 - MIT +

      + https://github.com/abrkn/semaphore.js +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5624,18 +6629,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    578. -
    579. -
      - - sorted-array-functions 1.3.0 - MIT - -

      https://github.com/mafintosh/sorted-array-functions

      -
      • Copyright (c) 2016 Mathias Buus
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    580. +
    581. +
      + sorted-array-functions 1.3.0 - MIT +

      + https://github.com/mafintosh/sorted-array-functions +

      +
        +
      • Copyright (c) 2016 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Mathias Buus
      @@ -5657,18 +6668,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    582. -
    583. -
      - - sparse-bitfield 3.0.3 - MIT - -

      https://github.com/mafintosh/sparse-bitfield

      -
      • Copyright (c) 2016 Mathias Buus
      -
      +
      +        
      +
      +
    584. +
    585. +
      + sparse-bitfield 3.0.3 - MIT +

      + https://github.com/mafintosh/sparse-bitfield +

      +
        +
      • Copyright (c) 2016 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Mathias Buus
      @@ -5690,18 +6706,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    586. -
    587. -
      - - split 1.0.1 - MIT - -

      http://github.com/dominictarr/split

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    588. +
    589. +
      + split 1.0.1 - MIT +

      + http://github.com/dominictarr/split +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               Copyright (c) 2011 Dominic Tarr
       
       Permission is hereby granted, free of charge, 
      @@ -5723,18 +6744,23 @@ 

      NOTICES AND INFORMATION

      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    590. -
    591. -
      - - stream-combiner 0.2.2 - MIT - -

      https://github.com/dominictarr/stream-combiner

      -
      • Copyright (c) 2012 Dominic Tarr
      -
      +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    592. +
    593. +
      + stream-combiner 0.2.2 - MIT +

      + https://github.com/dominictarr/stream-combiner +

      +
        +
      • Copyright (c) 2012 Dominic Tarr
      • +
      +
               Copyright (c) 2012 'Dominic Tarr'
       
       Permission is hereby granted, free of charge, 
      @@ -5757,18 +6783,25 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    594. -
    595. -
      - - string_decoder 1.1.1 - MIT - -

      https://github.com/nodejs/string_decoder

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    596. +
    597. +
      + string_decoder 1.1.1 - MIT +

      + https://github.com/nodejs/string_decoder +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Node.js is licensed for use as follows:
       
       """
      @@ -5817,18 +6850,16 @@ 

      NOTICES AND INFORMATION

      IN THE SOFTWARE. """ - -
      -
      -
    598. -
    599. -
      - - tas-client 0.1.45 - MIT - - - -
      +
      +        
      +
      +
    600. +
    601. +
      + tas-client 0.1.45 - MIT + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5837,18 +6868,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    602. -
    603. -
      - - through 2.3.8 - MIT - -

      https://github.com/dominictarr/through

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    604. +
    605. +
      + through 2.3.8 - MIT +

      + https://github.com/dominictarr/through +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -5873,18 +6909,21 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    606. -
    607. -
      - - tr46 0.0.3 - MIT - -

      https://github.com/Sebmaster/tr46.js#readme

      - -
      +
      +        
      +
      +
    608. +
    609. +
      + tr46 0.0.3 - MIT +

      + https://github.com/Sebmaster/tr46.js#readme +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5893,18 +6932,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    610. -
    611. -
      - - tunnel 0.0.6 - MIT - -

      https://github.com/koichik/node-tunnel/

      -
      • Copyright (c) 2012 Koichi Kobayashi
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    612. +
    613. +
      + tunnel 0.0.6 - MIT +

      + https://github.com/koichik/node-tunnel/ +

      +
        +
      • Copyright (c) 2012 Koichi Kobayashi
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 Koichi Kobayashi
      @@ -5926,19 +6970,31 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    614. -
    615. -
      - - underscore 1.12.1 - MIT - -

      https://underscorejs.org/

      -
      • Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore
      -
      +
      +        
      +
      +
    616. +
    617. +
      + underscore 1.12.1 - MIT +

      + https://underscorejs.org/ +

      +
        +
      • + Copyright (c) 2009-2020 Jeremy Ashkenas, + DocumentCloud and Investigative Reporters & + Editors +
      • +
      • + (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors Underscore +
      • +
      +
               Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative
       Reporters & Editors
       
      @@ -5962,18 +7018,26 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    618. -
    619. -
      - - universalify 0.1.2 - MIT - -

      https://github.com/RyanZim/universalify#readme

      -
      • Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
      -
      +
      +        
      +
      +
    620. +
    621. +
      + universalify 0.1.2 - MIT +

      + https://github.com/RyanZim/universalify#readme +

      +
        +
      • + Copyright (c) 2017, Ryan Zimmerman + <opensrc@ryanzim.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
      @@ -5994,18 +7058,26 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    622. -
    623. -
      - - util-deprecate 1.0.2 - MIT - -

      https://github.com/TooTallNate/util-deprecate

      -
      • Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    624. +
    625. +
      + util-deprecate 1.0.2 - MIT +

      + https://github.com/TooTallNate/util-deprecate +

      +
        +
      • + Copyright (c) 2014 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
      @@ -6030,20 +7102,34 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    626. -
    627. -
      - - uuid 3.4.0 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +
      +        
      +
      +
    628. +
    629. +
      + uuid 3.4.0 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2016 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2016 Robert Kieffer and other contributors
      @@ -6065,20 +7151,34 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    630. -
    631. -
      - - uuid 8.3.2 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2020 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +
      +        
      +
      +
    632. +
    633. +
      + uuid 8.3.2 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2020 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2020 Robert Kieffer and other contributors
      @@ -6088,20 +7188,34 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    634. -
    635. -
      - - uuid 9.0.1 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2020 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +
      +        
      +
      +
    636. +
    637. +
      + uuid 9.0.1 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2020 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2020 Robert Kieffer and other contributors
      @@ -6111,146 +7225,96 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    638. -
    639. -
      - - vscode-json-languageservice 3.5.2 - MIT - -

      https://github.com/Microsoft/vscode-json-languageservice#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      -        The MIT License (MIT)
      -
      -Copyright (c) Microsoft
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    640. -
    641. -
      - - vscode-jsonrpc 5.0.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    642. -
    643. -
      - - vscode-languageclient 6.1.3 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    644. -
    645. -
      - - vscode-languageserver 6.1.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    646. -
    647. -
      - - vscode-languageserver-protocol 3.15.3 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) TypeFox and others.
      • -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    648. -
    649. -
      - - vscode-languageserver-textdocument 1.0.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    650. +
    651. +
      + vscode-json-languageservice 3.5.2 - MIT +

      + https://github.com/Microsoft/vscode-json-languageservice#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) Microsoft
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    652. +
    653. +
      + vscode-jsonrpc 5.0.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    654. +
    655. +
      + vscode-languageclient 6.1.3 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6262,41 +7326,144 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    656. -
    657. -
      - - vscode-languageserver-types 3.15.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    658. -
    659. -
      - - vscode-nls 4.1.2 - MIT - -

      https://github.com/Microsoft/vscode-nls#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    660. +
    661. +
      + vscode-languageserver 6.1.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    662. +
    663. +
      + + vscode-languageserver-protocol 3.15.3 - MIT + +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) TypeFox and others.
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    664. +
    665. +
      + + vscode-languageserver-textdocument 1.0.1 - MIT + +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    666. +
    667. +
      + vscode-languageserver-types 3.15.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    668. +
    669. +
      + vscode-nls 4.1.2 - MIT +

      + https://github.com/Microsoft/vscode-nls#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft Corporation
      @@ -6314,18 +7481,19 @@ 

      NOTICES AND INFORMATION

      OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    670. -
    671. -
      - - vscode-tas-client 0.1.47 - MIT - - -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    672. +
    673. +
      + vscode-tas-client 0.1.47 - MIT + +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -6334,19 +7502,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    674. -
    675. -
      - - vscode-uri 1.0.8 - MIT - -

      https://github.com/Microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    676. +
    677. +
      + vscode-uri 1.0.8 - MIT +

      + https://github.com/Microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6355,19 +7528,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    678. -
    679. -
      - - vscode-uri 2.1.2 - MIT - -

      https://github.com/Microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    680. +
    681. +
      + vscode-uri 2.1.2 - MIT +

      + https://github.com/Microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6376,20 +7554,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    682. -
    683. -
      - - vscode-uri 3.0.7 - MIT - -

      https://github.com/microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    684. +
    685. +
      + vscode-uri 3.0.7 - MIT +

      + https://github.com/microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6398,19 +7583,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    686. -
    687. -
      - - whatwg-url 5.0.0 - MIT - -

      https://github.com/jsdom/whatwg-url#readme

      -
      • (c) extraPathPercentEncodeSet.has
      • -
      • Copyright (c) 2015-2016 Sebastian Mayr
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    688. +
    689. +
      + whatwg-url 5.0.0 - MIT +

      + https://github.com/jsdom/whatwg-url#readme +

      +
        +
      • (c) extraPathPercentEncodeSet.has
      • +
      • Copyright (c) 2015-2016 Sebastian Mayr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2015–2016 Sebastian Mayr
      @@ -6432,18 +7622,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    690. -
    691. -
      - - xml2js 0.5.0 - MIT - -

      https://github.com/Leonidas-from-XIV/node-xml2js

      -
      • Copyright 2010, 2011, 2012, 2013
      -
      +
      +        
      +
      +
    692. +
    693. +
      + xml2js 0.5.0 - MIT +

      + https://github.com/Leonidas-from-XIV/node-xml2js +

      +
        +
      • Copyright 2010, 2011, 2012, 2013
      • +
      +
               Copyright 2010, 2011, 2012, 2013. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -6463,51 +7659,61 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    694. -
    695. -
      - - xmlbuilder 11.0.1 - MIT - -

      http://github.com/oozcitak/xmlbuilder-js

      -
      • Copyright (c) 2013 Ozgur Ozcitak
      -
      -        The MIT License (MIT)
      -
      -Copyright (c) 2013 Ozgur Ozcitak
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in
      -all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      -THE SOFTWARE.
      -
      -        
      -
      -
    696. -
    697. -
      - - xtend 4.0.2 - MIT - -

      https://github.com/Raynos/xtend

      -
      • Copyright (c) 2012-2014 Raynos
      -
      +
      +        
      +
      +
    698. +
    699. +
      + xmlbuilder 11.0.1 - MIT +

      + http://github.com/oozcitak/xmlbuilder-js +

      +
        +
      • Copyright (c) 2013 Ozgur Ozcitak
      • +
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) 2013 Ozgur Ozcitak
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in
      +all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      +THE SOFTWARE.
      +
      +        
      +
      +
    700. +
    701. +
      + xtend 4.0.2 - MIT +

      + https://github.com/Raynos/xtend +

      +
        +
      • Copyright (c) 2012-2014 Raynos
      • +
      +
               The MIT License (MIT)
       Copyright (c) 2012-2014 Raynos.
       
      @@ -6528,18 +7734,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    702. -
    703. -
      - - JSONStream 1.3.5 - MIT OR Apache-2.0 - -

      http://github.com/dominictarr/JSONStream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    704. +
    705. +
      + JSONStream 1.3.5 - MIT OR Apache-2.0 +

      + http://github.com/dominictarr/JSONStream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -6564,18 +7775,19 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    706. -
    707. -
      - - pause-stream 0.0.11 - MIT OR Apache-2.0 - - -
      • Copyright (c) 2013 Dominic Tarr
      -
      +
      +        
      +
      +
    708. +
    709. +
      + pause-stream 0.0.11 - MIT OR Apache-2.0 + +
        +
      • Copyright (c) 2013 Dominic Tarr
      • +
      +
               Dual Licensed MIT and Apache 2
       
       The MIT License
      @@ -6806,10 +8018,11 @@ 

      NOTICES AND INFORMATION

      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. -
      -
      -
    710. -
    - - \ No newline at end of file + limitations under the License. +
    +
    +
  14. +
+ + diff --git a/README.md b/README.md index 4df65aec6..f8518c0a5 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,163 @@ - -# Azure Databases for VS Code (Preview) - - - -[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) - - - -Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). - -![Azure Databases Extension](resources/readme/overview.png) - -> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). - -# Prerequisites - -- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). - -# Features - -## Azure Databases Explorer - -- Create a database server by clicking the `+` button in the title -- View database servers and open directly in the portal -- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries -- Click on a document, stored procedure, or query to open in the editor -- Edit a document and persist changes to the cloud -- Attach a Mongo server by clicking the plug icon in the title - -![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) - -## Mongo Scrapbooks -### Run Mongo Commands with Rich Intellisense - -- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string -- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) -- Click on "New Mongo Scrapbook" in the tree title bar -- Click on "Connect to a database" to indicate which database to run the commands against -- Enter your commands and/or comments, eg: `db..find()` -- IntelliSense (auto-completions) will be provided -- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor -- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` -- Save and re-use later -![Mongo Scrapbook](resources/readme/Scrapbook.gif) - -## Import into Cosmos DB - -- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! -![Import documents](resources/readme/import_documents.gif) - -## Create an Azure Databases Server - -1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer - > If you don't already have an Azure Account, click "Create a Free Azure Account" -1. Select the 'plus' button to open the "Create Resource" menu - - ![Create resource](resources/readme/createResource.png) - -1. Choose "Create Database Server..." - - ![Create Database Server](resources/readme/createDatabaseServer.png) - -## Attach to the Cosmos DB Emulator - -* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine -* Right click 'Attached Database Accounts' and select 'Attach Emulator' - -![Attach Emulator](resources/readme/attachEmulator.png) - -## Known Issues - -- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. -- Graphs are not currently supported with the emulator -- Viewing/editing tables is not currently supported -- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). - - - -# Contributing -There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): - -* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. -* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! -* **Code**: Contribute bug fixes, features or design changes: - * Clone the repository locally and open in VS Code. - * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" - * Open the terminal (press CTRL+ \`) and run `npm install`. - * To build, press F1 and type in `Tasks: Run Build Task`. - * Debug: press F5 to start debugging the extension. - -## Legal -Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. - -## Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - - - -# Telemetry -VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). - -# License -[MIT](LICENSE.md) +# Azure Databases for VS Code (Preview) + + + +[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) +[![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) + + + +Browse and query your Azure databases both locally and in the cloud using +[_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure +to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, +Graph (Gremlin), and SQL (previously known as DocumentDB). + +![Azure Databases Extension](resources/readme/overview.png) + +> Sign up today for your free Azure account and receive 12 months of free +> popular services, $200 free credit and 25+ always free services 👉 +> [Start Free](https://azure.microsoft.com/free/open-source). + +# Prerequisites + +- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and + use of the Mongo shell require installing + [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). + +# Features + +## Azure Databases Explorer + +- Create a database server by clicking the `+` button in the title +- View database servers and open directly in the portal +- View/Create/Delete databases, collections, graphs, stored procedures, + documents, and queries +- Click on a document, stored procedure, or query to open in the editor +- Edit a document and persist changes to the cloud +- Attach a Mongo server by clicking the plug icon in the title + +![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) + +## Mongo Scrapbooks + +### Run Mongo Commands with Rich Intellisense + +- View your MongoDB database account by by clicking "Sign in to Azure..." in + the Azure Resources explorer or using "Attach Database Account" to connect + via a connection string +- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` + if your mongo executable is not already on your system's PATH (many of the + common commands have built-in support and do not require the Mongo shell to + be installed - see [Prerequisites](#prerequisites)) +- Click on "New Mongo Scrapbook" in the tree title bar +- Click on "Connect to a database" to indicate which database to run the + commands against +- Enter your commands and/or comments, eg: `db..find()` +- IntelliSense (auto-completions) will be provided +- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or + `CTRL+"` (Windows and Linux) to execute the line with the cursor +- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` +- Save and re-use later ![Mongo Scrapbook](resources/readme/Scrapbook.gif) + +## Import into Cosmos DB + +- You can now import documents from your workspace into CosmosDB. Use the + context menu of a collection or a document file (json) to get started! + ![Import documents](resources/readme/import_documents.gif) + +## Create an Azure Databases Server + +1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure + Resources explorer + > If you don't already have an Azure Account, click "Create a Free Azure + > Account" +1. Select the 'plus' button to open the "Create Resource" menu + + ![Create resource](resources/readme/createResource.png) + +1. Choose "Create Database Server..." + + ![Create Database Server](resources/readme/createDatabaseServer.png) + +## Attach to the Cosmos DB Emulator + +- Install and run the + [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) + on your local machine +- Right click 'Attached Database Accounts' and select 'Attach Emulator' + +![Attach Emulator](resources/readme/attachEmulator.png) + +## Known Issues + +- Azure no longer supports gremlin queries on pre-GA graph accounts. If you + see the error "Could not find a valid gremlin endpoint for _graph_", then + choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in + the Overview tab. If it does not take the form of + '...[graph-name].**_gremlin_**.cosmosdb.azure.com...', then you will need to + create a new graph account using the Azure portal or the current version of + the extension. +- Graphs are not currently supported with the emulator +- Viewing/editing tables is not currently supported +- Support for escapes in the scrapbooks is preliminary. We currently do not + support escaped characters as is inside a string - the characters need to be + double escaped. For example, newlines in the string should be '\\\\n' + instead of '\\n' to be recognized correctly. If you find any issues with how + the scrapbook handles escapes, please add to issue + [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). + + + +# Contributing + +There are several ways you can contribute to our +[repo](https://github.com/Microsoft/vscode-cosmosdb): + +- **Ideas, feature requests and bugs**: We are open to all ideas and we want + to get rid of bugs! Use the + [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to + report a new issue, provide your ideas or contribute to existing threads. +- **Documentation**: Found a typo or strangely worded sentences? Submit a PR! +- **Code**: Contribute bug fixes, features or design changes: + - Clone the repository locally and open in VS Code. + - Run "Extensions: Show Recommended Extensions" from the + [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) + and install all extensions listed under "Workspace Recommendations" + - Open the terminal (press CTRL+ \`) and run + `npm install`. + - To build, press F1 and type in `Tasks: Run Build Task`. + - Debug: press F5 to start debugging the extension. + +## Legal + +Before we can accept your pull request you will need to sign a **Contribution +License Agreement**. All you need to do is to submit a pull request, then the PR +will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, +`cla-signed`, `cla-already-signed`). If you already signed the agreement we will +continue with reviewing the PR, otherwise system will tell you how you can sign +the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. + +## Code of Conduct + +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the +[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any +additional questions or comments. + + + +# Telemetry + +VS Code collects usage data and sends it to Microsoft to help improve our +products and services. Read our +[privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) +to learn more. If you don’t wish to send usage data to Microsoft, you can set +the `telemetry.enableTelemetry` setting to `false`. Learn more in our +[FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). + +# License + +[MIT](LICENSE.md) diff --git a/Source/AzureDBExperiences.ts b/Source/AzureDBExperiences.ts index be9765dc6..97d2221cc 100644 --- a/Source/AzureDBExperiences.ts +++ b/Source/AzureDBExperiences.ts @@ -3,116 +3,202 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { nonNullProp } from './utils/nonNull'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; +import { nonNullProp } from "./utils/nonNull"; export enum API { - MongoDB = 'MongoDB', - Graph = 'Graph', - Table = 'Table', - Core = 'Core', - PostgresSingle = 'PostgresSingle', - PostgresFlexible = 'PostgresFlexible' + MongoDB = "MongoDB", + Graph = "Graph", + Table = "Table", + Core = "Core", + PostgresSingle = "PostgresSingle", + PostgresFlexible = "PostgresFlexible", } export enum DBAccountKind { - MongoDB = 'MongoDB', - GlobalDocumentDB = 'GlobalDocumentDB' + MongoDB = "MongoDB", + GlobalDocumentDB = "GlobalDocumentDB", } -export type CapabilityName = 'EnableGremlin' | 'EnableTable'; +export type CapabilityName = "EnableGremlin" | "EnableTable"; export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; - } - return info; + let info = experiencesMap.get(api); + if (!info) { + info = { + api: api, + shortName: api, + longName: api, + kind: DBAccountKind.GlobalDocumentDB, + tag: api, + }; + } + return info; } -export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { - - const experience: Experience | undefined = tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); - const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); - return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); - +export function getExperienceLabel( + databaseAccount: DatabaseAccountGetResults +): string { + const experience: Experience | undefined = + tryGetExperience(databaseAccount); + if (experience) { + return experience.shortName; + } + // Must be some new kind of resource that we aren't aware of. Try to get a decent label + const defaultExperience: string = ( + (databaseAccount && + databaseAccount.tags && + databaseAccount.tags.defaultExperience) + ); + const firstCapability = + databaseAccount.capabilities && databaseAccount.capabilities[0]; + const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ""); + return ( + defaultExperience || + firstCapabilityName || + nonNullProp(databaseAccount, "kind") + ); } -export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { - return GremlinExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; +export function tryGetExperience( + resource: DatabaseAccountGetResults +): Experience | undefined { + // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type + if (resource.kind === DBAccountKind.MongoDB) { + return MongoExperience; + } else if ( + resource.capabilities?.find((cap) => cap.name === "EnableGremlin") + ) { + return GremlinExperience; + } else if ( + resource.capabilities?.find((cap) => cap.name === "EnableTable") + ) { + return TableExperience; + } else if (resource.capabilities?.length === 0) { + return CoreExperience; + } + + return undefined; } export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; + /** + * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) + */ + api: API; - longName: string; - shortName: string; - description?: string; + longName: string; + shortName: string; + description?: string; - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; + // These properties are what the portal actually looks at to determine the difference between APIs + kind?: DBAccountKind; + capability?: CapabilityName; - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; + // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) + tag?: string; } -export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } +export function getExperienceQuickPicks( + attached?: boolean +): IAzureQuickPickItem[] { + if (attached) { + return experiencesArray.map((exp) => + getExperienceQuickPickForAttached(exp.api) + ); + } else { + return experiencesArray.map((exp) => getExperienceQuickPick(exp.api)); + } } -export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } +export function getCosmosExperienceQuickPicks( + attached?: boolean +): IAzureQuickPickItem[] { + if (attached) { + return cosmosExperiencesArray.map((exp) => + getExperienceQuickPickForAttached(exp.api) + ); + } else { + return cosmosExperiencesArray.map((exp) => + getExperienceQuickPick(exp.api) + ); + } } -export function getExperienceQuickPick(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; +export function getExperienceQuickPick( + api: API +): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.longName, description: exp.description, data: exp }; } -export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; +export function getExperienceQuickPickForAttached( + api: API +): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.shortName, description: exp.description, data: exp }; } // Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" // Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; -export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; -export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; -export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; -const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; -const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; - -const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; -const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; -const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); +export const CoreExperience: Experience = { + api: API.Core, + longName: "Core", + description: "(SQL)", + shortName: "SQL", + kind: DBAccountKind.GlobalDocumentDB, + tag: "Core (SQL)", +} as const; +export const MongoExperience: Experience = { + api: API.MongoDB, + longName: "Azure Cosmos DB for MongoDB API", + shortName: "MongoDB", + kind: DBAccountKind.MongoDB, + tag: "Azure Cosmos DB for MongoDB API", +} as const; +export const TableExperience: Experience = { + api: API.Table, + longName: "Azure Table", + shortName: "Table", + kind: DBAccountKind.GlobalDocumentDB, + capability: "EnableTable", + tag: "Azure Table", +} as const; +export const GremlinExperience: Experience = { + api: API.Graph, + longName: "Gremlin", + description: "(graph)", + shortName: "Gremlin", + kind: DBAccountKind.GlobalDocumentDB, + capability: "EnableGremlin", + tag: "Gremlin (graph)", +} as const; +const PostgresSingleExperience: Experience = { + api: API.PostgresSingle, + longName: "PostgreSQL Single Server", + shortName: "PostgreSQLSingle", +}; +const PostgresFlexibleExperience: Experience = { + api: API.PostgresFlexible, + longName: "PostgreSQL Flexible Server", + shortName: "PostgreSQLFlexible", +}; + +const cosmosExperiencesArray: Experience[] = [ + CoreExperience, + MongoExperience, + TableExperience, + GremlinExperience, +]; +const experiencesArray: Experience[] = [ + ...cosmosExperiencesArray, + PostgresSingleExperience, + PostgresFlexibleExperience, +]; +const experiencesMap = new Map( + experiencesArray.map((info: Experience): [API, Experience] => [ + info.api, + info, + ]) +); diff --git a/Source/DatabasesFileSystem.ts b/Source/DatabasesFileSystem.ts index 93c2b4938..da2073ac0 100644 --- a/Source/DatabasesFileSystem.ts +++ b/Source/DatabasesFileSystem.ts @@ -3,7 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import { + AzExtTreeFileSystem, + AzExtTreeItem, + DialogResponses, + IActionContext, + UserCancelledError, +} from "@microsoft/vscode-azext-utils"; import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; import { FileChangeType } from "vscode-languageclient"; import { ext } from "./extensionVariables"; @@ -12,66 +18,103 @@ import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; import { getNodeEditorLabel } from "./utils/vscodeUtils"; export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; + id: string; + filePath: string; + cTime: number; + mTime: number; + getFileContent(context: IActionContext): Promise; + writeFileContent(context: IActionContext, data: string): Promise; } export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = 'azureDatabases'; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; + public static scheme: string = "azureDatabases"; + public scheme: string = DatabasesFileSystem.scheme; + private _showSaveConfirmation: boolean = true; - public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { - const size: number = Buffer.byteLength(await node.getFileContent(context)); - return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; - } + public async statImpl( + context: IActionContext, + node: IEditableTreeItem + ): Promise { + const size: number = Buffer.byteLength( + await node.getFileContent(context) + ); + return { + type: FileType.File, + ctime: node.cTime, + mtime: node.mTime, + size, + }; + } - public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { - return Buffer.from(await node.getFileContent(context)); - } + public async readFileImpl( + context: IActionContext, + node: IEditableTreeItem + ): Promise { + return Buffer.from(await node.getFileContent(context)); + } - public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { - const showSavePromptKey: string = 'showSavePrompt'; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = 'cosmosDB'; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { - const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); - const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError('dontUpload'); - } - } + public async writeFileImpl( + context: IActionContext, + node: IEditableTreeItem, + content: Uint8Array, + _originalUri: Uri + ): Promise { + const showSavePromptKey: string = "showSavePrompt"; + // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" + const prefix: string = "cosmosDB"; + const nodeEditorLabel: string = getNodeEditorLabel(node); + if ( + this._showSaveConfirmation && + getWorkspaceSetting(showSavePromptKey, undefined, prefix) + ) { + const message: string = localize( + "saveConfirmation", + 'Saving "{0}" will update the entity "{1}" to the cloud.', + node.filePath, + nodeEditorLabel + ); + const result: MessageItem | undefined = + await context.ui.showWarningMessage( + message, + { stepName: "writeFile" }, + DialogResponses.upload, + DialogResponses.alwaysUpload, + DialogResponses.dontUpload + ); + if (result === DialogResponses.alwaysUpload) { + await updateGlobalSetting(showSavePromptKey, false, prefix); + } else if (result === DialogResponses.dontUpload) { + throw new UserCancelledError("dontUpload"); + } + } - await node.writeFileContent(context, content.toString()); - await node.refresh(context); + await node.writeFileContent(context, content.toString()); + await node.refresh(context); - const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); - ext.outputChannel.appendLog(updatedMessage); - } + const updatedMessage: string = localize( + "updatedEntity", + 'Updated entity "{0}".', + nodeEditorLabel + ); + ext.outputChannel.appendLog(updatedMessage); + } - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } + public getFilePath(node: IEditableTreeItem): string { + return node.filePath; + } - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } + public async updateWithoutPrompt(uri: Uri): Promise { + const textDoc = await workspace.openTextDocument(uri); + this._showSaveConfirmation = false; + try { + await textDoc.save(); + } finally { + this._showSaveConfirmation = true; + } + } - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } + public fireChangedEvent(node: IEditableTreeItem): void { + node.mTime = Date.now(); + this.fireSoon({ type: FileChangeType.Changed, item: node }); + } } diff --git a/Source/ParsedConnectionString.ts b/Source/ParsedConnectionString.ts index 99654ef5a..1619d6390 100644 --- a/Source/ParsedConnectionString.ts +++ b/Source/ParsedConnectionString.ts @@ -4,25 +4,27 @@ *--------------------------------------------------------------------------------------------*/ export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; + public abstract readonly hostName: string; + public abstract readonly port: string; - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; + /** + * databaseName may be undefined if this is an account-level connection string + */ + public readonly databaseName: string | undefined; + public readonly connectionString: string; - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } + constructor(connectionString: string, databaseName: string | undefined) { + this.connectionString = connectionString; + this.databaseName = databaseName; + } - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } + public get accountId(): string { + return `${this.hostName}:${this.port}`; + } - public get fullId(): string { - return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; - } + public get fullId(): string { + return `${this.accountId}${ + this.databaseName ? "/" + this.databaseName : "" + }`; + } } diff --git a/Source/azureAccountUtils.ts b/Source/azureAccountUtils.ts index 7f37da4cd..fbd474ae3 100644 --- a/Source/azureAccountUtils.ts +++ b/Source/azureAccountUtils.ts @@ -9,23 +9,32 @@ import { getApiExport } from "./getExtensionApi"; const azureAccountExtensionId = "ms-vscode.azure-account"; type AzureSession = { - userId: string; + userId: string; }; /** * @returns The user session of the signed-in azure account. */ -export async function getAzureAdUserSession(): Promise { - const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; +export async function getAzureAdUserSession(): Promise< + AzureSession | undefined +> { + const azureAccountExport = (await getApiExport( + azureAccountExtensionId + )) as { sessions?: AzureSession[] }; + return azureAccountExport.sessions?.[0]; } /** * Gets a function that can request an access token for a specified scope for the signed-in azure account. */ -export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { - return async () => { - const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; - return getTokenResult?.token ?? ""; - }; +export function getTokenFunction( + credentials: AzExtServiceClientCredentials, + scope: string +): () => Promise { + return async () => { + const getTokenResult = (await credentials.getToken(scope)) as + | { token: string } + | undefined; + return getTokenResult?.token ?? ""; + }; } diff --git a/Source/commands/api/DatabaseAccountTreeItemInternal.ts b/Source/commands/api/DatabaseAccountTreeItemInternal.ts index 89a8c1164..6a5cebe8a 100644 --- a/Source/commands/api/DatabaseAccountTreeItemInternal.ts +++ b/Source/commands/api/DatabaseAccountTreeItemInternal.ts @@ -3,104 +3,146 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { API } from '../../AzureDBExperiences'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { API } from "../../AzureDBExperiences"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { ParsedPostgresConnectionString } from "../../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { nonNullProp } from "../../utils/nonNull"; +import { DatabaseAccountTreeItem } from "../../vscode-cosmosdb.api"; -export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { - protected _parsedCS: ParsedConnectionString; - private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; +export class DatabaseAccountTreeItemInternal + implements DatabaseAccountTreeItem +{ + protected _parsedCS: ParsedConnectionString; + private _accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + | undefined; - constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } + constructor( + parsedCS: ParsedConnectionString, + accountNode?: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + ) { + this._parsedCS = parsedCS; + this._accountNode = accountNode; + } - public get connectionString(): string { - return this._parsedCS.connectionString; - } + public get connectionString(): string { + return this._parsedCS.connectionString; + } - public get hostName(): string { - return this._parsedCS.hostName; - } + public get hostName(): string { + return this._parsedCS.hostName; + } - public get port(): string { - return this._parsedCS.port; - } + public get port(): string { + return this._parsedCS.port; + } - public get azureData(): { accountName: string, accountId: string } | undefined { - if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), - accountId: this._accountNode.fullId - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId - }; - } - } - return undefined; - } + public get azureData(): + | { accountName: string; accountId: string } + | undefined { + if ( + this._accountNode instanceof MongoAccountTreeItem || + this._accountNode instanceof DocDBAccountTreeItemBase + ) { + if (this._accountNode?.databaseAccount) { + return { + accountName: nonNullProp( + this._accountNode.databaseAccount, + "name" + ), + accountId: this._accountNode.fullId, + }; + } + } else if (this._accountNode instanceof PostgresServerTreeItem) { + if (this._accountNode.azureName) { + return { + accountName: this._accountNode.azureName, + accountId: this._accountNode.fullId, + }; + } + } + return undefined; + } - public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey - }; - } else { - return undefined; - } - } + public get docDBData(): + | { masterKey: string; documentEndpoint: string } + | undefined { + if (this._accountNode instanceof DocDBAccountTreeItemBase) { + return { + documentEndpoint: this._accountNode.root.endpoint, + masterKey: this._accountNode.root.masterKey, + }; + } else { + return undefined; + } + } - public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password - }; - } else { - return undefined; - } - } + public get postgresData(): + | { username: string | undefined; password: string | undefined } + | undefined { + if (this._parsedCS instanceof ParsedPostgresConnectionString) { + const connectionString = this._parsedCS; + return { + username: connectionString.username, + password: connectionString.password, + }; + } else { + return undefined; + } + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); - }); - } + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling( + "api.dbAccount.reveal", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + await ext.rgApi.appResourceTreeView.reveal( + await this.getAccountNode(context) + ); + } + ); + } - protected async getAccountNode(context: IActionContext): Promise { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { + protected async getAccountNode( + context: IActionContext + ): Promise< + MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem + > { + // If this._accountNode is undefined, attach a new node based on connection string + if (!this._accountNode) { + let apiType: API; + if (this._parsedCS instanceof ParsedMongoConnectionString) { + apiType = API.MongoDB; + } else if ( + this._parsedCS instanceof ParsedPostgresConnectionString + ) { + apiType = API.PostgresSingle; + } else { + apiType = API.Core; + } + this._accountNode = + await ext.attachedAccountsNode.attachConnectionString( + context, + this.connectionString, + apiType + ); + } - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); - } - - return this._accountNode; - } + return this._accountNode; + } } diff --git a/Source/commands/api/DatabaseTreeItemInternal.ts b/Source/commands/api/DatabaseTreeItemInternal.ts index 9d6b0d140..8fa8389b2 100644 --- a/Source/commands/api/DatabaseTreeItemInternal.ts +++ b/Source/commands/api/DatabaseTreeItemInternal.ts @@ -3,40 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { DatabaseTreeItem } from "../../vscode-cosmosdb.api"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; +export class DatabaseTreeItemInternal + extends DatabaseAccountTreeItemInternal + implements DatabaseTreeItem +{ + public databaseName: string; + private _dbNode: AzExtTreeItem | undefined; - constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } + constructor( + parsedCS: ParsedConnectionString, + databaseName: string, + accountNode?: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem, + dbNode?: + | MongoDatabaseTreeItem + | DocDBDatabaseTreeItemBase + | PostgresDatabaseTreeItem + ) { + super(parsedCS, accountNode); + this.databaseName = databaseName; + this._dbNode = dbNode; + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling( + "api.db.reveal", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); - } + const accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem = + await this.getAccountNode(context); + if (!this._dbNode) { + const databaseId = `${accountNode.fullId}/${this.databaseName}`; + this._dbNode = + await ext.rgApi.workspaceResourceTree.findTreeItem( + databaseId, + context + ); + } - await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); - }); - } + await ext.rgApi.workspaceResourceTreeView.reveal( + this._dbNode || accountNode + ); + } + ); + } } diff --git a/Source/commands/api/apiCache.ts b/Source/commands/api/apiCache.ts index 30da342aa..9020478fd 100644 --- a/Source/commands/api/apiCache.ts +++ b/Source/commands/api/apiCache.ts @@ -3,44 +3,68 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; +import { ParsedDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { + ParsedPostgresConnectionString, + parsePostgresConnectionString, +} from "../../postgres/postgresConnectionStrings"; +import { + DatabaseAccountTreeItem, + DatabaseTreeItem, +} from "../../vscode-cosmosdb.api"; /** * This cache is used to speed up api calls from other extensions to the Cosmos DB extension * For now, it only helps on a per-session basis */ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = new Map(); +const sessionCache: Map = + new Map(); -export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { - sessionCache.set(parsedCS.fullId, treeItem); +export function cacheTreeItem( + parsedCS: ParsedConnectionString, + treeItem: DatabaseAccountTreeItem | DatabaseTreeItem +): void { + sessionCache.set(parsedCS.fullId, treeItem); } -export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); +export function tryGetTreeItemFromCache( + parsedCS: ParsedConnectionString +): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { + return sessionCache.get(parsedCS.fullId); } -export function removeTreeItemFromCache(expected: ParsedConnectionString): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); - } else { - actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); - } - if (actual && (actual.accountId === expected.accountId)) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } +export function removeTreeItemFromCache( + expected: ParsedConnectionString +): void { + if (!expected.databaseName) { + // If parsedCS represents an account, remove the account and any databases that match that account + for (const [key, value] of sessionCache.entries()) { + let actual: ParsedConnectionString | undefined; + if (expected instanceof ParsedPostgresConnectionString) { + actual = parsePostgresConnectionString(value.connectionString); + } else if (expected instanceof ParsedMongoConnectionString) { + actual = new ParsedMongoConnectionString( + value.connectionString, + value.hostName, + value.port, + undefined + ); + } else { + actual = new ParsedDocDBConnectionString( + value.connectionString, + value.hostName, + value.port, + undefined + ); + } + if (actual && actual.accountId === expected.accountId) { + sessionCache.delete(key); + } + } + } else { + sessionCache.delete(expected.fullId); + } } diff --git a/Source/commands/api/findTreeItem.ts b/Source/commands/api/findTreeItem.ts index 088413e52..d7e0f0d01 100644 --- a/Source/commands/api/findTreeItem.ts +++ b/Source/commands/api/findTreeItem.ts @@ -3,144 +3,223 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -export async function findTreeItem(query: TreeItemQuery): Promise { - return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, 'connectionString'); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = await rootNode.getCachedChildren(context); - result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - }); +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { + createPostgresConnectionString, + parsePostgresConnectionString, +} from "../../postgres/postgresConnectionStrings"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { SubscriptionTreeItem } from "../../tree/SubscriptionTreeItem"; +import { nonNullProp } from "../../utils/nonNull"; +import { + DatabaseAccountTreeItem, + DatabaseTreeItem, + TreeItemQuery, +} from "../../vscode-cosmosdb.api"; +import { cacheTreeItem, tryGetTreeItemFromCache } from "./apiCache"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; + +export async function findTreeItem( + query: TreeItemQuery +): Promise { + return await callWithTelemetryAndErrorHandling( + "api.findTreeItem", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + + let parsedCS: ParsedConnectionString; + if (query.postgresData) { + const postgresData = query.postgresData; + const connectionString: string = createPostgresConnectionString( + postgresData.hostName, + postgresData.port, + postgresData.username, + postgresData.password, + postgresData.databaseName + ); + parsedCS = parsePostgresConnectionString(connectionString); + } else { + const connectionString = nonNullProp(query, "connectionString"); + if (/^mongodb[^:]*:\/\//i.test(connectionString)) { + parsedCS = + await parseMongoConnectionString(connectionString); + } else if (/^postgres:\/\//i.test(connectionString)) { + parsedCS = parsePostgresConnectionString(connectionString); + } else { + parsedCS = parseDocDBConnectionString(connectionString); + } + } + + const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account + + // 1. Get result from cache if possible + let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = + tryGetTreeItemFromCache(parsedCS); + + // 2. Search attached accounts (do this before subscriptions because it's faster) + if (!result) { + const attachedDbAccounts = + await ext.attachedAccountsNode.getCachedChildren(context); + result = await searchDbAccounts( + attachedDbAccounts, + parsedCS, + context, + maxTime + ); + } + + // 3. Search subscriptions + if (!result) { + const rootNodes = await ext.rgApi.appResourceTree.getChildren(); + for (const rootNode of rootNodes) { + if (Date.now() > maxTime) { + break; + } + + if (rootNode instanceof SubscriptionTreeItem) { + const dbAccounts = + await rootNode.getCachedChildren(context); + result = await searchDbAccounts( + dbAccounts, + parsedCS, + context, + maxTime + ); + if (result) { + break; + } + } + } + } + + // 4. If all else fails, just attach a new node + if (!result) { + if (parsedCS.databaseName) { + result = new DatabaseTreeItemInternal( + parsedCS, + parsedCS.databaseName + ); + } else { + result = new DatabaseAccountTreeItemInternal(parsedCS); + } + } + + cacheTreeItem(parsedCS, result); + + return result; + } + ); } -async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); - } - if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); - } else { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); - } - - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); - } else { - return new DatabaseAccountTreeItemInternal(expected, dbAccount); - } - - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; +async function searchDbAccounts( + dbAccounts: AzExtTreeItem[], + expected: ParsedConnectionString, + context: IActionContext, + maxTime: number +): Promise { + try { + for (const dbAccount of dbAccounts) { + if (Date.now() > maxTime) { + return undefined; + } + + let actual: ParsedConnectionString; + if (dbAccount instanceof MongoAccountTreeItem) { + actual = await parseMongoConnectionString( + dbAccount.connectionString + ); + } else if (dbAccount instanceof DocDBAccountTreeItemBase) { + actual = parseDocDBConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof PostgresServerTreeItem) { + actual = dbAccount.partialConnectionString; + } else { + return undefined; + } + + if (expected.accountId === actual.accountId) { + if (expected.databaseName) { + const dbs = await dbAccount.getCachedChildren(context); + for (const db of dbs) { + if ( + (db instanceof MongoDatabaseTreeItem || + db instanceof DocDBDatabaseTreeItemBase) && + expected.databaseName === db.databaseName + ) { + return new DatabaseTreeItemInternal( + expected, + expected.databaseName, + dbAccount, + db + ); + } + if ( + db instanceof PostgresDatabaseTreeItem && + dbAccount instanceof PostgresServerTreeItem && + expected.databaseName === db.databaseName + ) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal( + fullConnectionString, + expected.databaseName, + dbAccount, + db + ); + } + } + + // We found the right account - just not the db. In this case we can still 'reveal' the account + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal( + fullConnectionString, + expected.databaseName, + dbAccount + ); + } else { + return new DatabaseTreeItemInternal( + expected, + expected.databaseName, + dbAccount + ); + } + } + + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseAccountTreeItemInternal( + fullConnectionString, + dbAccount + ); + } else { + return new DatabaseAccountTreeItemInternal( + expected, + dbAccount + ); + } + } + } + } catch (error) { + // Swallow all errors to avoid blocking the db account search + // https://github.com/microsoft/vscode-cosmosdb/issues/966 + } + + return undefined; } diff --git a/Source/commands/api/pickTreeItem.ts b/Source/commands/api/pickTreeItem.ts index dc84ce55a..f67ab039d 100644 --- a/Source/commands/api/pickTreeItem.ts +++ b/Source/commands/api/pickTreeItem.ts @@ -3,98 +3,146 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; -import { databaseAccountType } from '../../constants'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { localize } from '../../utils/localize'; -import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { PickAppResourceOptions } from "@microsoft/vscode-azext-utils/hostapi"; +import { databaseAccountType } from "../../constants"; +import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItem } from "../../docdb/tree/DocDBDatabaseTreeItem"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { GraphDatabaseTreeItem } from "../../graph/tree/GraphDatabaseTreeItem"; +import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { localize } from "../../utils/localize"; +import { + AzureDatabasesApiType, + DatabaseAccountTreeItem, + DatabaseTreeItem, + PickTreeItemOptions, +} from "../../vscode-cosmosdb.api"; +import { cacheTreeItem } from "./apiCache"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; -const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; +const databaseContextValues = [ + MongoDatabaseTreeItem.contextValue, + DocDBDatabaseTreeItem.contextValue, + GraphDatabaseTreeItem.contextValue, + PostgresDatabaseTreeItem.contextValue, +]; function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case 'Mongo': - return MongoDatabaseTreeItem.contextValue; - case 'SQL': - return DocDBDatabaseTreeItem.contextValue; - case 'Graph': - return GraphDatabaseTreeItem.contextValue; - case 'Postgres': - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } + switch (apiType) { + case "Mongo": + return MongoDatabaseTreeItem.contextValue; + case "SQL": + return DocDBDatabaseTreeItem.contextValue; + case "Graph": + return GraphDatabaseTreeItem.contextValue; + case "Postgres": + return PostgresDatabaseTreeItem.contextValue; + default: + throw new RangeError(`Unsupported api type "${apiType}".`); + } } +export async function pickTreeItem( + pickTreeOptions: PickTreeItemOptions +): Promise { + return await callWithTelemetryAndErrorHandling( + "api.pickTreeItem", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; -export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { - return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + const options: PickAppResourceOptions = {}; + switch (pickTreeOptions.resourceType) { + case "Database": + options.filter = { type: databaseAccountType }; + options.expectedChildContextValue = pickTreeOptions.apiType + ? pickTreeOptions.apiType.map(getDatabaseContextValue) + : databaseContextValues; + break; + case "DatabaseAccount": + options.filter = { type: databaseAccountType }; + break; + default: + throw new RangeError( + `Unsupported resource type "${pickTreeOptions.resourceType}".` + ); + } - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case 'Database': - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType ? - pickTreeOptions.apiType.map(getDatabaseContextValue) : - databaseContextValues; - break; - case 'DatabaseAccount': - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); - } + const pickedItem = await ext.rgApi.pickAppResource( + context, + options + ); - const pickedItem = await ext.rgApi.pickAppResource(context, options); + let parsedCS: ParsedConnectionString; + let accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem; + let databaseNode: + | MongoDatabaseTreeItem + | DocDBDatabaseTreeItemBase + | PostgresDatabaseTreeItem + | undefined; + if (pickedItem instanceof MongoAccountTreeItem) { + parsedCS = await parseMongoConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem; + } else if (pickedItem instanceof DocDBAccountTreeItemBase) { + parsedCS = parseDocDBConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem; + } else if (pickedItem instanceof PostgresServerTreeItem) { + parsedCS = await pickedItem.getFullConnectionString(); + accountNode = pickedItem; + } else if (pickedItem instanceof MongoDatabaseTreeItem) { + parsedCS = await parseMongoConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { + parsedCS = parseDocDBConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof PostgresDatabaseTreeItem) { + parsedCS = await pickedItem.parent.getFullConnectionString(); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else { + throw new RangeError( + localize( + "invalidItem", + 'Invalid item "{0}".', + pickedItem.constructor.name + ) + ); + } - let parsedCS: ParsedConnectionString; - let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; - let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); - } - - const result = databaseNode ? - new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : - new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - }); + const result = databaseNode + ? new DatabaseTreeItemInternal( + parsedCS, + databaseNode.databaseName, + accountNode, + databaseNode + ) + : new DatabaseAccountTreeItemInternal(parsedCS, accountNode); + cacheTreeItem(parsedCS, result); + return result; + } + ); } diff --git a/Source/commands/api/revealTreeItem.ts b/Source/commands/api/revealTreeItem.ts index d13589351..185ff340c 100644 --- a/Source/commands/api/revealTreeItem.ts +++ b/Source/commands/api/revealTreeItem.ts @@ -3,14 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { ext } from "../../extensionVariables"; export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); - } - }); + return await callWithTelemetryAndErrorHandling( + "api.revealTreeItem", + async (context: IActionContext) => { + const node: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem(resourceId, { + ...context, + loadAll: true, + }); + if (node) { + await ext.rgApi.appResourceTreeView.reveal(node, { + select: true, + focus: true, + expand: true, + }); + } + } + ); } diff --git a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts index 1ef9ca645..d409dcc0a 100644 --- a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts @@ -7,13 +7,13 @@ import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } + public async execute(context: IDeleteWizardContext): Promise { + await context.node.deleteTreeItem(context); + } - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } + public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { + return true; + } } diff --git a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts index 762beb96e..e20bafa90 100644 --- a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts @@ -1,13 +1,20 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + ExecuteActivityContext, + IActionContext, + ISubscriptionContext, +} from "@microsoft/vscode-azext-utils"; -export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; +export interface IDeleteWizardContext + extends IActionContext, + ExecuteActivityContext { + node: AzExtTreeItem; + deletePostgres: boolean; + resourceGroupToDelete?: string; + subscription: ISubscriptionContext; } diff --git a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts index a90956b30..b862cb33e 100644 --- a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts @@ -3,30 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; -import { localize } from '../../utils/localize'; -import { IDeleteWizardContext } from './IDeleteWizardContext'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; +import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { ext } from "../../extensionVariables"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { getDatabaseAccountNameFromId } from "../../utils/azureUtils"; +import { localize } from "../../utils/localize"; +import { IDeleteWizardContext } from "./IDeleteWizardContext"; -export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await deletePromise; - const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } else { - await deletePromise; - } +export async function deleteCosmosDBAccount( + context: IDeleteWizardContext, + node: AzExtTreeItem +): Promise { + const client: CosmosDBManagementClient = await createCosmosDBClient([ + context, + node.subscription, + ]); + const resourceGroup: string = getResourceGroupFromId(node.fullId); + const accountName: string = getDatabaseAccountNameFromId(node.fullId); + const deletePromise = client.databaseAccounts.beginDeleteAndWait( + resourceGroup, + accountName + ); + if (!context.suppressNotification) { + const deletingMessage: string = `Deleting account "${accountName}"...`; + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: deletingMessage, + }, + async () => { + await deletePromise; + const deleteMessage: string = localize( + "deleteAccountMsg", + `Successfully deleted account "{0}".`, + accountName + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + } + ); + } else { + await deletePromise; + } } diff --git a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts index 4792710d4..ac6857848 100644 --- a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts @@ -3,35 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + AzureWizard, + DeleteConfirmationStep, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { createActivityContext } from "../../utils/activityUtils"; import { localize } from "../../utils/localize"; import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; +export async function deleteDatabaseAccount( + context: IActionContext, + node: AzExtTreeItem, + isPostgres: boolean = false +): Promise { + const wizardContext: IDeleteWizardContext = Object.assign(context, { + node, + deletePostgres: isPostgres, + subscription: node.subscription, + ...(await createActivityContext()), + }); -export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()) - }); + const title = wizardContext.deletePostgres + ? localize("deletePoSer", 'Delete Postgres Server "{0}"', node.label) + : localize("deleteDbAcc", 'Delete Database Account "{0}"', node.label); - const title = wizardContext.deletePostgres ? - localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : - localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) + const confirmationMessage = wizardContext.deletePostgres + ? localize( + "deleteAccountConfirm", + 'Are you sure you want to delete server "{0}" and its contents?', + node.label + ) + : localize( + "deleteAccountConfirm", + 'Are you sure you want to delete account "{0}" and its contents?', + node.label + ); - const confirmationMessage = wizardContext.deletePostgres ? - localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : - localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); + const wizard = new AzureWizard(wizardContext, { + title, + promptSteps: [new DeleteConfirmationStep(confirmationMessage)], + executeSteps: [new DatabaseAccountDeleteStep()], + }); - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()] - }); - - await wizard.prompt(); - await wizard.execute(); + await wizard.prompt(); + await wizard.execute(); } diff --git a/Source/commands/importDocuments.ts b/Source/commands/importDocuments.ts index bd4c83e3f..305af31eb 100644 --- a/Source/commands/importDocuments.ts +++ b/Source/commands/importDocuments.ts @@ -3,161 +3,209 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from '@azure/cosmos'; -import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { cosmosMongoFilter, sqlFilter } from '../constants'; -import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; -import { ext } from '../extensionVariables'; -import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { getRootPath } from '../utils/workspacUtils'; +import { ItemDefinition } from "@azure/cosmos"; +import { IActionContext, parseError } from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import * as vscode from "vscode"; +import { cosmosMongoFilter, sqlFilter } from "../constants"; +import { DocDBCollectionTreeItem } from "../docdb/tree/DocDBCollectionTreeItem"; +import { ext } from "../extensionVariables"; +import { MongoCollectionTreeItem } from "../mongo/tree/MongoCollectionTreeItem"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { getRootPath } from "../utils/workspacUtils"; -export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); - ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents..." - }, - async (progress) => { - uris = nonNullValue(uris, 'uris'); - collectionNode = nonNullValue(collectionNode, 'collectionNode'); +export async function importDocuments( + context: IActionContext, + uris: vscode.Uri[] | undefined, + collectionNode: + | MongoCollectionTreeItem + | DocDBCollectionTreeItem + | undefined +): Promise { + if (!uris) { + uris = await askForDocuments(context); + } + const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 + uris = uris.filter((uri) => { + if (uri.fsPath.toLocaleLowerCase().endsWith(".json")) { + return true; + } else { + ignoredUris.push(uri); + return false; + } + }); + if (ignoredUris.length) { + ext.outputChannel.appendLog( + `Ignoring the following files which are not json:` + ); + ignoredUris.forEach((uri) => + ext.outputChannel.appendLine(`${uri.fsPath}`) + ); + ext.outputChannel.show(); + } + if (!collectionNode) { + collectionNode = await ext.rgApi.pickAppResource< + MongoCollectionTreeItem | DocDBCollectionTreeItem + >(context, { + filter: [cosmosMongoFilter, sqlFilter], + expectedChildContextValue: [ + MongoCollectionTreeItem.contextValue, + DocDBCollectionTreeItem.contextValue, + ], + }); + } + let result: string; + result = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Importing documents...", + }, + async (progress) => { + uris = nonNullValue(uris, "uris"); + collectionNode = nonNullValue(collectionNode, "collectionNode"); - progress.report({ increment: 20, message: "Parsing documents for errors" }); - const documents = await parseDocuments(uris); - progress.report({ increment: 30, message: "Parsed documents. Importing" }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo(collectionNode, documents); - } else { - result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); + progress.report({ + increment: 20, + message: "Parsing documents for errors", + }); + const documents = await parseDocuments(uris); + progress.report({ + increment: 30, + message: "Parsed documents. Importing", + }); + if (collectionNode instanceof MongoCollectionTreeItem) { + result = await insertDocumentsIntoMongo( + collectionNode, + documents + ); + } else { + result = await insertDocumentsIntoDocdb( + collectionNode, + documents, + uris + ); + } + progress.report({ increment: 50, message: "Finished importing" }); + return result; + } + ); - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); + await collectionNode.refresh(context); + await vscode.window.showInformationMessage(result); } async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"] - } - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); + const openDialogOptions: vscode.OpenDialogOptions = { + canSelectMany: true, + openLabel: "Import", + filters: { + JSON: ["json"], + }, + }; + const rootPath: string | undefined = getRootPath(); + if (rootPath) { + openDialogOptions.defaultUri = vscode.Uri.file(rootPath); + } + return await context.ui.showOpenDialog(openDialogOptions); } // eslint-disable-next-line @typescript-eslint/no-explicit-any async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let documents: any[] = []; + let errorFoundFlag: boolean = false; + for (const uri of uris) { + let parsed; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + parsed = await fse.readJSON(uri.fsPath); + } catch (e) { + if (!errorFoundFlag) { + errorFoundFlag = true; + ext.outputChannel.appendLog( + "Errors found in documents listed below. Please fix these." + ); + ext.outputChannel.show(); + } + const err = parseError(e); + ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); + } + if (parsed) { + if (Array.isArray(parsed)) { + documents = documents.concat(parsed); + } else { + documents.push(parsed); + } + } + } + if (errorFoundFlag) { + throw new Error( + `Errors found in some documents. Please see the output, fix these and try again.` + ); + } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return documents; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); - erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); - ext.outputChannel.show(); - throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); - } - for (const document of documents) { - const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; +async function insertDocumentsIntoDocdb( + collectionNode: DocDBCollectionTreeItem, + documents: any[], + uris: vscode.Uri[] +): Promise { + const ids: string[] = []; + let i = 0; + const erroneousFiles: vscode.Uri[] = []; + for (i = 0; i < documents.length; i++) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const document: ItemDefinition = documents[i]; + if ( + !collectionNode.documentsTreeItem.documentHasPartitionKey(document) + ) { + erroneousFiles.push(uris[i]); + } + } + if (erroneousFiles.length) { + ext.outputChannel.appendLog( + `The following documents do not contain the required partition key:` + ); + erroneousFiles.forEach((file) => + ext.outputChannel.appendLine(file.path) + ); + ext.outputChannel.show(); + throw new Error( + `See output for list of documents that do not contain the partition key '${ + nonNullProp(collectionNode, "partitionKey").paths[0] + }' required by collection '${collectionNode.label}'` + ); + } + for (const document of documents) { + const retrieved: ItemDefinition = + await collectionNode.documentsTreeItem.createDocument(document); + if (retrieved.id) { + ids.push(retrieved.id); + } + } + const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; + for (const id of ids) { + ext.outputChannel.appendLine(`Inserted document: ${id}`); + } + return result; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; +async function insertDocumentsIntoMongo( + node: MongoCollectionTreeItem, + documents: any[] +): Promise { + let output = ""; + const parsed = await node.collection.insertMany(documents); + if (parsed.result && parsed.result.ok) { + output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; + for (const inserted of Object.values(parsed.insertedIds)) { + ext.outputChannel.appendLine(`Inserted document: ${inserted}`); + } + } + return output; } diff --git a/Source/constants.ts b/Source/constants.ts index 0e6a4a14e..4d43ec018 100644 --- a/Source/constants.ts +++ b/Source/constants.ts @@ -5,47 +5,62 @@ export const isWindows: boolean = /^win/.test(process.platform); -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; -import { ext } from './extensionVariables'; +import * as assert from "assert"; +import * as fs from "fs"; +import * as path from "path"; +import { + CoreExperience, + GremlinExperience, + MongoExperience, + TableExperience, +} from "./AzureDBExperiences"; +import { ext } from "./extensionVariables"; export namespace Links { - export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; + export const LocalConnectionDebuggingTips: string = + "https://aka.ms/AA5zah5"; } export interface IThemedIconPath { - light: string; - dark: string; + light: string; + dark: string; } export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'light', iconName), - dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), "icons", "light", iconName), + dark: path.join(getResourcesPath(), "icons", "dark", iconName), + }; + assert(fs.existsSync(a.light)); + return a; } export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), - dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join( + getResourcesPath(), + "icons", + "theme-agnostic", + iconName + ), + dark: path.join( + getResourcesPath(), + "icons", + "theme-agnostic", + iconName + ), + }; + assert(fs.existsSync(a.light)); + return a; } export function getResourcesPath(): string { - return ext.context.asAbsolutePath('resources'); + return ext.context.asAbsolutePath("resources"); } export const doubleClickDebounceDelay = 500; //milliseconds -export const defaultStoredProcedure = - `function sample(prefix) { +export const defaultStoredProcedure = `function sample(prefix) { var collection = getContext().getCollection(); // Query documents and take 1st item. @@ -70,67 +85,69 @@ export const defaultStoredProcedure = }); if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};` ; +};`; -export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; +export const emulatorPassword = + "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; // https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = 'test'; +export const testDb: string = "test"; -export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; -export const postgresLanguageId: string = 'postgres'; +export const connectedPostgresKey: string = + "ms-azuretools.vscode-azuredatabases.connectedPostgresDB"; +export const postgresLanguageId: string = "postgres"; export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = 'query'; -export const postgresDefaultPort = '5432'; -export const postgresDefaultDatabase = 'postgres'; -export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; +export const postgresBaseFileName: string = "query"; +export const postgresDefaultPort = "5432"; +export const postgresDefaultDatabase = "postgres"; +export const SERVERLESS_CAPABILITY_NAME = "EnableServerless"; -export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; +export const databaseAccountType = "Microsoft.DocumentDB/databaseAccounts"; export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag - } + type: databaseAccountType, + kind: MongoExperience.kind, + tags: { + defaultExperience: mongoDefaultExperienceTag, + }, }; -export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; +export const gremlinDefaultExperienceTag = "Gremlin (graph)"; export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag - } + type: databaseAccountType, + kind: GremlinExperience.kind, + tags: { + defaultExperience: gremlinDefaultExperienceTag, + }, }; -export const tableDefaultExperienceTag = 'Azure Table'; +export const tableDefaultExperienceTag = "Azure Table"; export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag - } + type: databaseAccountType, + kind: TableExperience.kind, + tags: { + defaultExperience: tableDefaultExperienceTag, + }, }; -export const sqlDefaultExperienceTag = 'Core (SQL)'; +export const sqlDefaultExperienceTag = "Core (SQL)"; export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag - } + type: databaseAccountType, + kind: CoreExperience.kind, + tags: { + defaultExperience: sqlDefaultExperienceTag, + }, }; export const postgresFlexibleFilter = { - type: 'Microsoft.DBforPostgreSQL/flexibleServers' + type: "Microsoft.DBforPostgreSQL/flexibleServers", }; export const postgresSingleFilter = { - type: 'Microsoft.DBForPostgreSQL/servers' + type: "Microsoft.DBForPostgreSQL/servers", }; diff --git a/Source/docdb/docDBConnectionStrings.ts b/Source/docdb/docDBConnectionStrings.ts index 946490d21..3389eeea4 100644 --- a/Source/docdb/docDBConnectionStrings.ts +++ b/Source/docdb/docDBConnectionStrings.ts @@ -3,40 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as url from 'url'; -import { ParsedConnectionString } from '../ParsedConnectionString'; -import { nonNullProp } from '../utils/nonNull'; +import * as url from "url"; +import { ParsedConnectionString } from "../ParsedConnectionString"; +import { nonNullProp } from "../utils/nonNull"; -export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); - const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); - const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); - if (!endpoint || !masterKey) { - throw new Error('Invalid Document DB connection string.'); - } - return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); +export function parseDocDBConnectionString( + connectionString: string +): ParsedDocDBConnectionString { + const endpoint = getPropertyFromConnectionString( + connectionString, + "AccountEndpoint" + ); + const masterKey = getPropertyFromConnectionString( + connectionString, + "AccountKey" + ); + const databaseName = getPropertyFromConnectionString( + connectionString, + "Database" + ); + if (!endpoint || !masterKey) { + throw new Error("Invalid Document DB connection string."); + } + return new ParsedDocDBConnectionString( + connectionString, + endpoint, + masterKey, + databaseName + ); } -function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; +function getPropertyFromConnectionString( + connectionString: string, + property: string +): string | undefined { + const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, "i"); + const match = connectionString.match(regexp); + return match ? match[1] : undefined; } export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - public readonly documentEndpoint: string; - public readonly masterKey: string; + public readonly documentEndpoint: string; + public readonly masterKey: string; - constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; + constructor( + connectionString: string, + endpoint: string, + masterKey: string, + databaseName: string | undefined + ) { + super(connectionString, databaseName); + this.documentEndpoint = endpoint; + this.masterKey = masterKey; - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, 'hostname'); - this.port = nonNullProp(parsedEndpoint, 'port'); - } + const parsedEndpoint = url.parse(endpoint); + this.hostName = nonNullProp(parsedEndpoint, "hostname"); + this.port = nonNullProp(parsedEndpoint, "port"); + } } diff --git a/Source/docdb/getCosmosClient.ts b/Source/docdb/getCosmosClient.ts index 3b285fc9c..f422ec3c2 100644 --- a/Source/docdb/getCosmosClient.ts +++ b/Source/docdb/getCosmosClient.ts @@ -6,14 +6,33 @@ import { CosmosClient } from "@azure/cosmos"; import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; import * as https from "https"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { ext } from "../extensionVariables"; -export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { - - const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; - return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); - +export function getCosmosClient( + endpoint: string, + key: string, + isEmulator: boolean | undefined +): CosmosClient { + const vscodeStrictSSL: boolean | undefined = vscode.workspace + .getConfiguration() + .get(ext.settingsKeys.vsCode.proxyStrictSSL); + const enableEndpointDiscovery: boolean | undefined = vscode.workspace + .getConfiguration() + .get(ext.settingsKeys.enableEndpointDiscovery); + const connectionPolicy = { + enableEndpointDiscovery: + enableEndpointDiscovery === undefined + ? true + : enableEndpointDiscovery, + }; + return new CosmosClient({ + endpoint, + key, + userAgentSuffix: appendExtensionUserAgent(), + agent: new https.Agent({ + rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL, + }), + connectionPolicy: connectionPolicy, + }); } diff --git a/Source/docdb/registerDocDBCommands.ts b/Source/docdb/registerDocDBCommands.ts index 5eb7545e4..a8f29c69d 100644 --- a/Source/docdb/registerDocDBCommands.ts +++ b/Source/docdb/registerDocDBCommands.ts @@ -3,7 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + IActionContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; import { commands } from "vscode"; import { doubleClickDebounceDelay, sqlFilter } from "../constants"; import { ext } from "../extensionVariables"; @@ -16,89 +21,170 @@ import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeI import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openDocument", documentNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); - } - const childNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - - } - await node.deleteTreeItem(context); - }); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBDatabase", + createDocDBDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBCollection", + createDocDBCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBDocument", + async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDocumentsTreeItem.contextValue + ); + } + const documentNode = ( + await node.createChild(context) + ); + await commands.executeCommand( + "cosmosDB.openDocument", + documentNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProceduresTreeItem + ) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProceduresTreeItem.contextValue + ); + } + const childNode = await node.createChild(context); + await commands.executeCommand( + "cosmosDB.openStoredProcedure", + childNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBDatabase", + deleteDocDBDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBCollection", + deleteDocDBCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProcedureTreeItem + ) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProcedureTreeItem.contextValue + ); + } + await ext.fileSystem.showTextDocument(node); + }, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBDocument", + async (context: IActionContext, node?: DocDBDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDocumentTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProcedureTreeItem + ) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProcedureTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); } -export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); - await databaseNode.createChild(context); +export async function createDocDBDatabase( + context: IActionContext, + node?: DocDBAccountTreeItem +): Promise { + if (!node) { + node = await pickDocDBAccount(context); + } + const databaseNode: DocDBDatabaseTreeItem = ( + await node.createChild(context) + ); + await databaseNode.createChild(context); } -export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.createChild(context); +export async function createDocDBCollection( + context: IActionContext, + node?: DocDBDatabaseTreeItem +): Promise { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDatabaseTreeItem.contextValue + ); + } + await node.createChild(context); } -export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteDocDBDatabase( + context: IActionContext, + node?: DocDBDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteDocDBCollection( + context: IActionContext, + node?: DocDBCollectionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - sqlFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickDocDBAccount( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [sqlFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/docdb/tree/DocDBAccountTreeItem.ts b/Source/docdb/tree/DocDBAccountTreeItem.ts index 0cee7ed06..242af5546 100644 --- a/Source/docdb/tree/DocDBAccountTreeItem.ts +++ b/Source/docdb/tree/DocDBAccountTreeItem.ts @@ -3,35 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { DatabaseDefinition, Resource } from "@azure/cosmos"; +import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBDocumentServer"; + public contextValue: string = DocDBAccountTreeItem.contextValue; - public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } + public initChild( + resource: DatabaseDefinition & Resource + ): DocDBDatabaseTreeItem { + this.valuesToMask.push(resource._rid, resource._self); + return new DocDBDatabaseTreeItem(this, resource); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case DocDBDatabaseTreeItem.contextValue: + case DocDBCollectionTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case DocDBDocumentsTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/docdb/tree/DocDBAccountTreeItemBase.ts b/Source/docdb/tree/DocDBAccountTreeItemBase.ts index da9eec6b7..2984b29ef 100644 --- a/Source/docdb/tree/DocDBAccountTreeItemBase.ts +++ b/Source/docdb/tree/DocDBAccountTreeItemBase.ts @@ -3,93 +3,139 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { rejectOnTimeout } from '../../utils/timeout'; -import { getCosmosClient } from '../getCosmosClient'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { + CosmosClient, + DatabaseDefinition, + DatabaseResponse, + FeedOptions, + QueryIterator, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { + SERVERLESS_CAPABILITY_NAME, + getThemeAgnosticIconPath, +} from "../../constants"; +import { nonNullProp } from "../../utils/nonNull"; +import { rejectOnTimeout } from "../../utils/timeout"; +import { getCosmosClient } from "../getCosmosClient"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class provides common logic for DocumentDB, Graph, and Table accounts * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; +export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase< + DatabaseDefinition & Resource +> { + public readonly label: string; + public readonly childTypeLabel: string = "Database"; + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + endpoint: string, + masterKey: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super(parent); + this.id = id; + this.label = label; + this.root = { + endpoint, + masterKey, + isEmulator, + getCosmosClient: () => + getCosmosClient(endpoint, masterKey, isEmulator), + }; - constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) - }; + this.valuesToMask.push(id, endpoint, masterKey); + } - this.valuesToMask.push(id, endpoint, masterKey); - } + public get connectionString(): string { + return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; + } - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("CosmosDBAccount.svg"); + } - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } + public get isServerless(): boolean { + return this.databaseAccount?.capabilities + ? this.databaseAccount.capabilities.some( + (cap) => cap.name === SERVERLESS_CAPABILITY_NAME + ) + : false; + } - public get isServerless(): boolean { - return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return client.databases.readAll(feedOptions); + } - } + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + validateInput: validateDatabaseName, + stepName: "createDatabase", + }); - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.databases.readAll(feedOptions); - } + const client = this.root.getCosmosClient(); + const database: DatabaseResponse = await client.databases.create({ + id: databaseName, + }); + return this.initChild(nonNullProp(database, "resource")); + } - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: 'Database Name', - validateInput: validateDatabaseName, - stepName: 'createDatabase' - }); + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (this.root.isEmulator) { + const unableToReachEmulatorMessage: string = + "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; + return await rejectOnTimeout( + 2000, + () => super.loadMoreChildrenImpl(clearCache), + unableToReachEmulatorMessage + ); + } else { + return await super.loadMoreChildrenImpl(clearCache); + } + } - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ id: databaseName }); - return this.initChild(nonNullProp(database, 'resource')); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } } function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; + if (!name || name.length < 1 || name.length > 255) { + return "Name has to be between 1 and 255 chars long"; + } + if (name.endsWith(" ")) { + return "Database name cannot end with space"; + } + if (/[/\\?#=]/.test(name)) { + return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBCollectionTreeItem.ts b/Source/docdb/tree/DocDBCollectionTreeItem.ts index 987bbe3b4..8849bee34 100644 --- a/Source/docdb/tree/DocDBCollectionTreeItem.ts +++ b/Source/docdb/tree/DocDBCollectionTreeItem.ts @@ -3,90 +3,115 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { + Container, + ContainerDefinition, + CosmosClient, + PartitionKeyDefinition, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * Represents a DocumentDB collection */ export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - } + public static contextValue: string = "cosmosDBDocumentCollection"; + public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; + public readonly documentsTreeItem: DocDBDocumentsTreeItem; + public readonly parent: DocDBDatabaseTreeItem; + + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + constructor( + parent: DocDBDatabaseTreeItem, + private _container: ContainerDefinition & Resource + ) { + super(parent); + this.parent = parent; + this.documentsTreeItem = new DocDBDocumentsTreeItem(this); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( + this + ); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._container.id; + } + + public get label(): string { + return this._container.id; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get link(): string { + return this._container._self; + } + + public get partitionKey(): PartitionKeyDefinition | undefined { + return this._container.partitionKey; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteCollection" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return [this.documentsTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public pickTreeItemImpl( + expectedContextValues: (string | RegExp)[] + ): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case DocDBDocumentsTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + return this.documentsTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getDatabaseClient(client).container(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItem.ts b/Source/docdb/tree/DocDBDatabaseTreeItem.ts index ee8c23694..b51504cc2 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItem.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItem.ts @@ -3,20 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; +import { + ContainerDefinition, + CosmosClient, + Database, + Resource, +} from "@azure/cosmos"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDatabaseTreeItemBase } from "./DocDBDatabaseTreeItemBase"; export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Collection'; + public static contextValue: string = "cosmosDBDocumentDatabase"; + public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; - public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } + public initChild( + container: ContainerDefinition & Resource + ): DocDBCollectionTreeItem { + return new DocDBCollectionTreeItem(this, container); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts index aa7e8d779..15a935e5c 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts @@ -3,12 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { + ContainerDefinition, + ContainerResponse, + CosmosClient, + DatabaseDefinition, + FeedOptions, + QueryIterator, + RequestOptions, + Resource, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; const minThroughputFixed: number = 400; const minThroughputPartitioned: number = 400; @@ -19,143 +34,177 @@ const throughputStepSize = 100; * This class provides common logic for DocumentDB, Graph, and Table databases * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public get id(): string { - return nonNullProp(this._database, 'id'); - } - - public get label(): string { - return nonNullProp(this._database, 'id'); - } - - public get link(): string { - return nonNullProp(this._database, '_self'); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.database(this._database.id).containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl(context: ICreateChildImplContext): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}` - }); - - const containerDefinition: ContainerDefinition = { - id: containerName - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey] - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !(containerDefinition.partitionKey); - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const throughput: number = Number(await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: 'throughputCapacity', - validateInput: (input: string) => validateThroughput(isFixed, input) - })); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, 'resource')); - } - - protected async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address/zipCode' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } +export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase< + ContainerDefinition & Resource +> { + public readonly parent: DocDBAccountTreeItemBase; + private readonly _database: DatabaseDefinition & Resource; + + constructor( + parent: DocDBAccountTreeItemBase, + database: DatabaseDefinition & Resource + ) { + super(parent); + this._database = database; + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("database"); + } + + public get id(): string { + return nonNullProp(this._database, "id"); + } + + public get label(): string { + return nonNullProp(this._database, "id"); + } + + public get link(): string { + return nonNullProp(this._database, "_self"); + } + + public get connectionString(): string { + return this.parent.connectionString.concat(`;Database=${this.id}`); + } + + public get databaseName(): string { + return this._database.id; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return client + .database(this._database.id) + .containers.readAll(feedOptions); + } + + // Delete the database + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteDatabase" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await client.database(this.id).delete(); + } + + // Create a DB collection + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const containerName = await context.ui.showInputBox({ + placeHolder: `Enter an id for your ${this.childTypeLabel}`, + validateInput: validateCollectionName, + stepName: `create${this.childTypeLabel}`, + }); + + const containerDefinition: ContainerDefinition = { + id: containerName, + }; + + const partitionKey = await this.getNewPartitionKey(context); + if (partitionKey) { + containerDefinition.partitionKey = { + paths: [partitionKey], + }; + } + const options: RequestOptions = {}; + + if (!this.parent.isServerless) { + const isFixed: boolean = !containerDefinition.partitionKey; + const minThroughput = isFixed + ? minThroughputFixed + : minThroughputPartitioned; + const throughput: number = Number( + await context.ui.showInputBox({ + value: minThroughput.toString(), + prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, + stepName: "throughputCapacity", + validateInput: (input: string) => + validateThroughput(isFixed, input), + }) + ); + + if (throughput !== 0) { + options.offerThroughput = throughput; + } + } + + context.showCreatingTreeItem(containerName); + const client = this.root.getCosmosClient(); + const container: ContainerResponse = await client + .database(this.id) + .containers.create(containerDefinition, options); + + return this.initChild(nonNullProp(container, "resource")); + } + + protected async getNewPartitionKey( + context: IActionContext + ): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: "Enter the partition key for the collection, or leave blank for fixed size.", + stepName: "partitionKeyForCollection", + validateInput: this.validatePartitionKey, + placeHolder: "e.g. /address/zipCode", + }); + + if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { + partitionKey = "/" + partitionKey; + } + + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + return undefined; + } } -function validateThroughput(isFixed: boolean, input: string): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const value = Number(input); - if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; +function validateThroughput( + isFixed: boolean, + input: string +): string | undefined | null { + if (input === "0") { + return undefined; + } + + try { + const minThroughput = isFixed + ? minThroughputFixed + : minThroughputPartitioned; + const value = Number(input); + if ( + value < minThroughput || + value > maxThroughput || + (value - minThroughput) % throughputStepSize !== 0 + ) { + return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; + } + } catch (err) { + return "Input must be a number"; + } + return undefined; } function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; + if (!name) { + return "Collection name cannot be empty"; + } + if (name.endsWith(" ")) { + return "Collection name cannot end with space"; + } + if (/[/\\?#]/.test(name)) { + return `Collection name cannot contain the characters '\\', '/', '#', '?'`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBDocumentTreeItem.ts b/Source/docdb/tree/DocDBDocumentTreeItem.ts index 1505572d9..408dedfd7 100644 --- a/Source/docdb/tree/DocDBDocumentTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentTreeItem.ts @@ -3,131 +3,171 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { sanitizeId } from './DocDBUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; +import { + CosmosClient, + Item, + ItemDefinition, + RequestOptions, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullProp } from "../../utils/nonNull"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { sanitizeId } from "./DocDBUtils"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; + +const hiddenFields: string[] = [ + "_rid", + "_self", + "_etag", + "_attachments", + "_ts", +]; /** * Represents a Cosmos DB DocumentDB (SQL) document */ -export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openDocument'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error(`The "_self" and "_etag" fields are required to update a document`); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; - const response = await this.getDocumentClient(client).replace(newData, options); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split('/'); - if (fields[0] === '') { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { //Partition Key exists, but this document doesn't have a value - return ''; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); - } +export class DocDBDocumentTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "cosmosDBDocument"; + public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; + public readonly parent: DocDBDocumentsTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + private _label: string; + private _document: ItemDefinition; + + constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { + super(parent); + this._document = document; + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + this.commandId = "cosmosDB.openDocument"; + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); + } + + public get filePath(): string { + return this.label + "-cosmos-document.json"; + } + + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + } + + public get link(): string { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return this.document._self; + } + + get document(): ItemDefinition { + return this._document; + } + + get label(): string { + return this._label; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("file"); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteDocument" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getDocumentClient(client).delete(); + } + + public async getFileContent(): Promise { + const clonedDoc: {} = { ...this.document }; + for (const field of hiddenFields) { + delete clonedDoc[field]; + } + return JSON.stringify(clonedDoc, null, 2); + } + + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const newData = JSON.parse(content); + for (const field of hiddenFields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + newData[field] = this.document[field]; + } + + const client: CosmosClient = this.root.getCosmosClient(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (["_etag"].some((element) => !newData[element])) { + throw new Error( + `The "_self" and "_etag" fields are required to update a document` + ); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const options: RequestOptions = { + accessCondition: { type: "IfMatch", condition: newData._etag }, + }; + const response = await this.getDocumentClient(client).replace( + newData, + options + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this._document = response.resource; + } + } + + private getPartitionKeyValue(): string | undefined | Object { + const partitionKey = this.parent.parent.partitionKey; + if (!partitionKey) { + //Fixed collections -> no partitionKeyValue + return undefined; + } + const fields = partitionKey.paths[0].split("/"); + if (fields[0] === "") { + fields.shift(); + } + let value; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + value = value ? value[field] : this.document[field]; + if (!value) { + //Partition Key exists, but this document doesn't have a value + return ""; + } + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + } + + private getDocumentClient(client: CosmosClient): Item { + return this.parent + .getContainerClient(client) + .item( + nonNullProp(this.document, "id"), + this.getPartitionKeyValue() + ); + } } diff --git a/Source/docdb/tree/DocDBDocumentsTreeItem.ts b/Source/docdb/tree/DocDBDocumentsTreeItem.ts index b8265444d..ec05451e0 100644 --- a/Source/docdb/tree/DocDBDocumentsTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentsTreeItem.ts @@ -3,127 +3,160 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; -import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { + Container, + CosmosClient, + FeedOptions, + ItemDefinition, + ItemResponse, + QueryIterator, +} from "@azure/cosmos"; +import { + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class provides logic for DocumentDB collections */ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = (await this.promptForPartitionKey(context, body)); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); - return nonNullProp(item, 'resource'); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split('/'); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { - const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: 'valueforParititionKey' - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { - //remove leading slash - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split('/'); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } + public static contextValue: string = "cosmosDBDocumentsGroup"; + public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; + public readonly childTypeLabel: string = "Documents"; + public readonly parent: DocDBCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get id(): string { + return "$Documents"; + } + + public get label(): string { + return "Documents"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return this.getContainerClient(client).items.readAll(feedOptions); + } + + public initChild(document: ItemDefinition): DocDBDocumentTreeItem { + return new DocDBDocumentTreeItem(this, document); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + let docID = await context.ui.showInputBox({ + prompt: "Enter a document ID or leave blank for a generated ID", + stepName: "createDocument", + }); + + docID = docID.trim(); + let body: ItemDefinition = { id: docID }; + body = await this.promptForPartitionKey(context, body); + context.showCreatingTreeItem(docID); + const item: ItemDefinition = await this.createDocument(body); + + return this.initChild(item); + } + + public async createDocument(body: ItemDefinition): Promise { + const item: ItemResponse = + await this.getContainerClient( + this.root.getCosmosClient() + ).items.create(body); + return nonNullProp(item, "resource"); + } + + public documentHasPartitionKey(doc: Object): boolean { + let interim = doc; + let partitionKey: string | undefined = + this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (!partitionKey) { + return true; + } + if (partitionKey[0] === "/") { + partitionKey = partitionKey.slice(1); + } + const partitionKeyPath = partitionKey.split("/"); + + for (const prop of partitionKeyPath) { + // eslint-disable-next-line no-prototype-builtins + if (interim.hasOwnProperty(prop)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[prop]; + } else { + return false; + } + } + return true; + } + + public async promptForPartitionKey( + context: IActionContext, + body: ItemDefinition + ): Promise { + const partitionKey: string | undefined = + this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (partitionKey) { + const partitionKeyValue: string = await context.ui.showInputBox({ + prompt: `Enter a value for the partition key ("${partitionKey}")`, + stepName: "valueforParititionKey", + }); + // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. + // We need to present the partitionKey value as part of the document contents + Object.assign( + body, + this.createPartitionPathObject(partitionKey, partitionKeyValue) + ); + } + return body; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + // Create a nested Object given the partition key path and value + private createPartitionPathObject( + partitionKey: string, + partitionKeyValue: string + ): Object { + //remove leading slash + if (partitionKey[0] === "/") { + partitionKey = partitionKey.slice(1); + } + const keyPath = partitionKey.split("/"); + const PartitionPath: Object = {}; + let interim: Object = PartitionPath; + let i: number; + for (i = 0; i < keyPath.length - 1; i++) { + interim[keyPath[i]] = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[keyPath[i]]; + } + interim[keyPath[i]] = partitionKeyValue; + return PartitionPath; + } } diff --git a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts index 899eccd27..20ced0d3e 100644 --- a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts @@ -3,74 +3,100 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * Represents a Cosmos DB DocumentDB (SQL) stored procedure */ -export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); +export class DocDBStoredProcedureTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "cosmosDBStoredProcedure"; + public readonly contextValue: string = + DocDBStoredProcedureTreeItem.contextValue; + public readonly cTime: number = Date.now(); + public readonly parent: DocDBStoredProceduresTreeItem; + public mTime: number = Date.now(); - constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openStoredProcedure'; - } + constructor( + parent: DocDBStoredProceduresTreeItem, + public procedure: StoredProcedureDefinition & Resource + ) { + super(parent); + ext.fileSystem.fireChangedEvent(this); + this.commandId = "cosmosDB.openStoredProcedure"; + } - public get root(): IDocDBTreeRoot { - return this.parent.root; - } + public get root(): IDocDBTreeRoot { + return this.parent.root; + } - public get filePath(): string { - return this.label + '-cosmos-stored-procedure.js'; - } + public get filePath(): string { + return this.label + "-cosmos-stored-procedure.js"; + } - public get id(): string { - return this.procedure.id; - } + public get id(): string { + return this.procedure.id; + } - public get label(): string { - return this.procedure.id; - } + public get label(): string { + return this.procedure.id; + } - public get link(): string { - return this.procedure._self; - } + public get link(): string { + return this.procedure._self; + } - public async getFileContent(): Promise { - return typeof this.procedure.body === 'string' ? this.procedure.body : ''; + public async getFileContent(): Promise { + return typeof this.procedure.body === "string" + ? this.procedure.body + : ""; + } - } + public async refreshImpl(): Promise { + ext.fileSystem.fireChangedEvent(this); + } - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + const client = this.root.getCosmosClient(); + const replace = await this.parent + .getContainerClient(client) + .scripts.storedProcedure(this.id) + .replace({ id: this.id, body: content }); + this.procedure = nonNullProp(replace, "resource"); + } - public async writeFileContent(_context: IActionContext, content: string): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, 'resource'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("server-process"); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteStoredProcedure" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.parent + .getContainerClient(client) + .scripts.storedProcedure(this.id) + .delete(); + } } diff --git a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts index 4c3ddfd1a..a869e8a99 100644 --- a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts @@ -3,95 +3,141 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { + Container, + CosmosClient, + FeedOptions, + QueryIterator, + Resource, + StoredProcedureDefinition, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; -import { defaultStoredProcedure } from '../../constants'; -import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { defaultStoredProcedure } from "../../constants"; +import { GraphCollectionTreeItem } from "../../graph/tree/GraphCollectionTreeItem"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class represents the DocumentDB "Stored Procedures" node in the tree */ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = (await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: 'createStoredProcedure', - validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) - })).trim(); - const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; - context.showCreatingTreeItem(spID); - const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, 'resource')); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize("nameLength", "Name has to be between 1 and 255 chars long"); - } - - if (/[/\\?#&]/.test(name)) { - return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); - } - - return undefined; - } + public static contextValue: string = "cosmosDBStoredProceduresGroup"; + public readonly contextValue: string = + DocDBStoredProceduresTreeItem.contextValue; + public readonly childTypeLabel: string = "Stored Procedure"; + public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public initChild( + resource: StoredProcedureDefinition & Resource + ): DocDBStoredProcedureTreeItem { + return new DocDBStoredProcedureTreeItem(this, resource); + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("server-process"); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const client = this.root.getCosmosClient(); + const currStoredProcedureList: AzExtTreeItem[] = + await this.getCachedChildren(context); + const currStoredProcedureNames: string[] = []; + for (const sp of currStoredProcedureList) { + currStoredProcedureNames.push(nonNullProp(sp, "id")); + } + const spID = ( + await context.ui.showInputBox({ + prompt: "Enter a unique stored procedure ID", + stepName: "createStoredProcedure", + validateInput: (name: string) => + this.validateStoredProcedureName( + name, + currStoredProcedureNames + ), + }) + ).trim(); + const body: StoredProcedureDefinition = { + id: spID, + body: defaultStoredProcedure, + }; + context.showCreatingTreeItem(spID); + const sproc = + await this.getContainerClient( + client + ).scripts.storedProcedures.create(body); + + return this.initChild(nonNullProp(sproc, "resource")); + } + + public get id(): string { + return "$StoredProcedures"; + } + + public get label(): string { + return "Stored Procedures"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return this.getContainerClient(client).scripts.storedProcedures.readAll( + feedOptions + ); + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + private validateStoredProcedureName( + name: string, + currStoredProcedureNames: string[] + ): string | undefined { + if (name.length < 1 || name.length > 255) { + return localize( + "nameLength", + "Name has to be between 1 and 255 chars long" + ); + } + + if (/[/\\?#&]/.test(name)) { + return localize( + "illegalChars", + "Name contains illegal chars: /, \\, ?, #, &" + ); + } + if (name[name.length - 1] === " ") { + return localize("endsWithSpace", "Name cannot end with a space."); + } + if (currStoredProcedureNames.includes(name)) { + return localize( + "nameExists", + 'Stored Procedure "{0}" already exists.', + name + ); + } + + return undefined; + } } diff --git a/Source/docdb/tree/DocDBTreeItemBase.ts b/Source/docdb/tree/DocDBTreeItemBase.ts index 4424603ae..0774fbcdc 100644 --- a/Source/docdb/tree/DocDBTreeItemBase.ts +++ b/Source/docdb/tree/DocDBTreeItemBase.ts @@ -3,53 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { CosmosClient, FeedOptions, QueryIterator } from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, +} from "@microsoft/vscode-azext-utils"; +import { getBatchSizeSetting } from "../../utils/workspacUtils"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * This class provides common iteration logic for DocumentDB accounts, databases, and collections */ export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; + public abstract readonly label: string; + public abstract readonly contextValue: string; + public abstract readonly childTypeLabel: string; - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); + private _hasMoreChildren: boolean = true; + private _iterator: QueryIterator | undefined; + private _batchSize: number = getBatchSizeSetting(); - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } - public root: IDocDBTreeRoot; + public root: IDocDBTreeRoot; - public abstract initChild(resource: T): AzExtTreeItem; + public abstract initChild(resource: T): AzExtTreeItem; - public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; + public abstract getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator; - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + } - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); - } + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache || this._iterator === undefined) { + this._hasMoreChildren = true; + const client = this.root.getCosmosClient(); + this._iterator = this.getIterator(client, { + maxItemCount: this._batchSize, + }); + } - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); + const resourceArray: T[] = []; + const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()) + .resources; + if (resourceFeed) { + resourceArray.push(...resourceFeed); + } + this._hasMoreChildren = this._iterator.hasMoreResults(); - this._batchSize *= 2; + this._batchSize *= 2; - return resourceArray.map((resource: T) => this.initChild(resource)); - } + return resourceArray.map((resource: T) => this.initChild(resource)); + } } diff --git a/Source/docdb/tree/DocDBUtils.ts b/Source/docdb/tree/DocDBUtils.ts index 3d45cf950..1a0630d53 100644 --- a/Source/docdb/tree/DocDBUtils.ts +++ b/Source/docdb/tree/DocDBUtils.ts @@ -8,5 +8,5 @@ * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding */ export function sanitizeId(id: string): string { - return id.replace(/\+/g, ' '); + return id.replace(/\+/g, " "); } diff --git a/Source/docdb/tree/IDocDBTreeRoot.ts b/Source/docdb/tree/IDocDBTreeRoot.ts index 9179eb454..6827564c2 100644 --- a/Source/docdb/tree/IDocDBTreeRoot.ts +++ b/Source/docdb/tree/IDocDBTreeRoot.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -7,8 +6,8 @@ import { CosmosClient } from "@azure/cosmos"; export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; + endpoint: string; + masterKey: string; + isEmulator: boolean | undefined; + getCosmosClient(): CosmosClient; } diff --git a/Source/extension.ts b/Source/extension.ts index e68744157..c712fbc4c 100644 --- a/Source/extension.ts +++ b/Source/extension.ts @@ -3,213 +3,409 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; -import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; -import { platform } from 'os'; -import * as vscode from 'vscode'; -import { DatabasesFileSystem } from './DatabasesFileSystem'; -import { findTreeItem } from './commands/api/findTreeItem'; -import { pickTreeItem } from './commands/api/pickTreeItem'; -import { revealTreeItem } from './commands/api/revealTreeItem'; -import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { importDocuments } from './commands/importDocuments'; -import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; -import { registerDocDBCommands } from './docdb/registerDocDBCommands'; -import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; -import { ext } from './extensionVariables'; -import { getResourceGroupsApi } from './getExtensionApi'; -import { registerGraphCommands } from './graph/registerGraphCommands'; -import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; -import { registerMongoCommands } from './mongo/registerMongoCommands'; -import { setConnectedNode } from './mongo/setConnectedNode'; -import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; -import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; -import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; -import { DatabaseResolver } from './resolver/AppResolver'; -import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; -import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; -import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; -import { localize } from './utils/localize'; - -const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; - -export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = 'true'; - activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); - - const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); - ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { - if (platform() !== 'win32') { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); - } - - await ext.attachedAccountsNode.attachEmulator(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh(actionContext, node); - } - }); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { - const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); - if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { - const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); - } - if (node instanceof MongoAccountTreeItem) { - if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments(actionContext, uris || [selectedNode], undefined); - } else { - await importDocuments(actionContext, undefined, selectedNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { - if (!node) { - node = await ext.rgApi.pickAppResource(actionContext, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); - registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); - registerEvent( - 'cosmosDB.onDidChangeConfiguration', - vscode.workspace.onDidChangeConfiguration, - async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { - actionContext.telemetry.properties.isActivationEvent = "true"; - actionContext.errorHandling.suppressDisplay = true; - if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { - await vscode.commands.executeCommand("azureDatabases.refresh"); - } - }); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); - registerReportIssueCommand('azureDatabases.reportIssue'); - }); - - return createApiProvider([{ - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: '1.2.0' - }]); +"use strict"; + +import { registerAzureUtilsExtensionVariables } from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + AzureExtensionApi, + IActionContext, + ITreeItemPickerContext, + apiUtils, + callWithTelemetryAndErrorHandling, + createApiProvider, + createAzExtOutputChannel, + registerCommandWithTreeNodeUnwrapping, + registerErrorHandler, + registerEvent, + registerReportIssueCommand, + registerUIExtensionVariables, +} from "@microsoft/vscode-azext-utils"; +import { AzExtResourceType } from "@microsoft/vscode-azureresources-api"; +import { platform } from "os"; +import * as vscode from "vscode"; +import { DatabasesFileSystem } from "./DatabasesFileSystem"; +import { findTreeItem } from "./commands/api/findTreeItem"; +import { pickTreeItem } from "./commands/api/pickTreeItem"; +import { revealTreeItem } from "./commands/api/revealTreeItem"; +import { deleteDatabaseAccount } from "./commands/deleteDatabaseAccount/deleteDatabaseAccount"; +import { importDocuments } from "./commands/importDocuments"; +import { + cosmosGremlinFilter, + cosmosMongoFilter, + cosmosTableFilter, + doubleClickDebounceDelay, + sqlFilter, +} from "./constants"; +import { registerDocDBCommands } from "./docdb/registerDocDBCommands"; +import { DocDBAccountTreeItem } from "./docdb/tree/DocDBAccountTreeItem"; +import { DocDBAccountTreeItemBase } from "./docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBCollectionTreeItem } from "./docdb/tree/DocDBCollectionTreeItem"; +import { DocDBDocumentTreeItem } from "./docdb/tree/DocDBDocumentTreeItem"; +import { ext } from "./extensionVariables"; +import { getResourceGroupsApi } from "./getExtensionApi"; +import { registerGraphCommands } from "./graph/registerGraphCommands"; +import { GraphAccountTreeItem } from "./graph/tree/GraphAccountTreeItem"; +import { registerMongoCommands } from "./mongo/registerMongoCommands"; +import { setConnectedNode } from "./mongo/setConnectedNode"; +import { MongoAccountTreeItem } from "./mongo/tree/MongoAccountTreeItem"; +import { MongoCollectionTreeItem } from "./mongo/tree/MongoCollectionTreeItem"; +import { MongoDocumentTreeItem } from "./mongo/tree/MongoDocumentTreeItem"; +import { registerPostgresCommands } from "./postgres/commands/registerPostgresCommands"; +import { DatabaseResolver } from "./resolver/AppResolver"; +import { DatabaseWorkspaceProvider } from "./resolver/DatabaseWorkspaceProvider"; +import { TableAccountTreeItem } from "./table/tree/TableAccountTreeItem"; +import { AttachedAccountSuffix } from "./tree/AttachedAccountsTreeItem"; +import { SubscriptionTreeItem } from "./tree/SubscriptionTreeItem"; +import { localize } from "./utils/localize"; + +const cosmosDBTopLevelContextValues: string[] = [ + GraphAccountTreeItem.contextValue, + DocDBAccountTreeItem.contextValue, + TableAccountTreeItem.contextValue, + MongoAccountTreeItem.contextValue, +]; + +export async function activateInternal( + context: vscode.ExtensionContext, + perfStats: { loadStartTime: number; loadEndTime: number }, + ignoreBundle?: boolean +): Promise { + ext.context = context; + ext.ignoreBundle = ignoreBundle; + + ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); + context.subscriptions.push(ext.outputChannel); + registerUIExtensionVariables(ext); + registerAzureUtilsExtensionVariables(ext); + + await callWithTelemetryAndErrorHandling( + "cosmosDB.activate", + async (activateContext: IActionContext) => { + activateContext.telemetry.properties.isActivationEvent = "true"; + activateContext.telemetry.measurements.mainFileLoad = + (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; + + ext.secretStorage = context.secrets; + + ext.rgApi = await getResourceGroupsApi(); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.AzureCosmosDb, + new DatabaseResolver() + ); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.PostgresqlServersStandard, + new DatabaseResolver() + ); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.PostgresqlServersFlexible, + new DatabaseResolver() + ); + + const workspaceRootTreeItem = ( + ext.rgApi.workspaceResourceTree as unknown as { + _rootTreeItem: AzExtParentTreeItem; + } + )._rootTreeItem; + const databaseWorkspaceProvider = new DatabaseWorkspaceProvider( + workspaceRootTreeItem + ); + ext.rgApi.registerWorkspaceResourceProvider( + "AttachedDatabaseAccount", + databaseWorkspaceProvider + ); + + ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); + + registerDocDBCommands(); + registerGraphCommands(); + registerPostgresCommands(); + registerMongoCommands(); + + context.subscriptions.push( + vscode.workspace.registerFileSystemProvider( + DatabasesFileSystem.scheme, + ext.fileSystem + ) + ); + + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.selectSubscriptions", + () => + vscode.commands.executeCommand( + "azure-account.selectSubscriptions" + ) + ); + + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.createServer", + createServer + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteAccount", + deleteAccount + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.attachDatabaseAccount", + async (actionContext: IActionContext) => { + await ext.attachedAccountsNode.attachNewAccount( + actionContext + ); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.attachEmulator", + async (actionContext: IActionContext) => { + if (platform() !== "win32") { + actionContext.errorHandling.suppressReportIssue = true; + throw new Error( + localize( + "emulatorNotSupported", + "The Cosmos DB emulator is only supported on Windows." + ) + ); + } + + await ext.attachedAccountsNode.attachEmulator( + actionContext + ); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.refresh", + async (actionContext: IActionContext, node?: AzExtTreeItem) => { + if (node) { + await node.refresh(actionContext); + } else { + await ext.rgApi.appResourceTree.refresh( + actionContext, + node + ); + } + } + ); + + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.detachDatabaseAccount", + async ( + actionContext: IActionContext & ITreeItemPickerContext, + node?: AzExtTreeItem + ) => { + const children = + await ext.attachedAccountsNode.loadAllChildren( + actionContext + ); + if ( + children[0].contextValue === + "cosmosDBAttachDatabaseAccount" + ) { + const message = localize( + "noAttachedAccounts", + "There are no Attached Accounts." + ); + void vscode.window.showInformationMessage(message); + } else { + if (!node) { + node = + await ext.rgApi.workspaceResourceTree.showTreeItemPicker( + cosmosDBTopLevelContextValues.map( + (val: string) => + (val += AttachedAccountSuffix) + ), + actionContext + ); + } + if (node instanceof MongoAccountTreeItem) { + if ( + ext.connectedMongoDB && + node.fullId === + ext.connectedMongoDB.parent.fullId + ) { + setConnectedNode(undefined); + await node.refresh(actionContext); + } + } + await ext.attachedAccountsNode.detach(node); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.importDocument", + async ( + actionContext: IActionContext, + selectedNode: + | vscode.Uri + | MongoCollectionTreeItem + | DocDBCollectionTreeItem, + uris: vscode.Uri[] + ) => { + if (selectedNode instanceof vscode.Uri) { + await importDocuments( + actionContext, + uris || [selectedNode], + undefined + ); + } else { + await importDocuments( + actionContext, + undefined, + selectedNode + ); + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.copyConnectionString", + cosmosDBCopyConnectionString + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openDocument", + async ( + actionContext: IActionContext, + node?: MongoDocumentTreeItem | DocDBDocumentTreeItem + ) => { + if (!node) { + node = await ext.rgApi.pickAppResource< + MongoDocumentTreeItem | DocDBDocumentTreeItem + >(actionContext, { + filter: [cosmosMongoFilter, sqlFilter], + expectedChildContextValue: [ + MongoDocumentTreeItem.contextValue, + DocDBDocumentTreeItem.contextValue, + ], + }); + } + + // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 + ext.fileSystem.fireChangedEvent(node); + await ext.fileSystem.showTextDocument(node); + }, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.update", + async (_actionContext: IActionContext, uri: vscode.Uri) => + await ext.fileSystem.updateWithoutPrompt(uri) + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.loadMore", + async (actionContext: IActionContext, node: AzExtTreeItem) => + await ext.rgApi.appResourceTree.loadMore( + node, + actionContext + ) + ); + registerEvent( + "cosmosDB.onDidChangeConfiguration", + vscode.workspace.onDidChangeConfiguration, + async ( + actionContext: IActionContext, + event: vscode.ConfigurationChangeEvent + ) => { + actionContext.telemetry.properties.isActivationEvent = + "true"; + actionContext.errorHandling.suppressDisplay = true; + if ( + event.affectsConfiguration( + ext.settingsKeys.documentLabelFields + ) + ) { + await vscode.commands.executeCommand( + "azureDatabases.refresh" + ); + } + } + ); + + // Suppress "Report an Issue" button for all errors in favor of the command + registerErrorHandler( + (c) => (c.errorHandling.suppressReportIssue = true) + ); + registerReportIssueCommand("azureDatabases.reportIssue"); + } + ); + + return createApiProvider([ + { + findTreeItem, + pickTreeItem, + revealTreeItem, + apiVersion: "1.2.0", + }, + ]); } // this method is called when your extension is deactivated export function deactivateInternal(): void { - // NOOP + // NOOP } -export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { - if (!node) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); - } +export async function createServer( + context: IActionContext, + node?: SubscriptionTreeItem +): Promise { + if (!node) { + node = + await ext.rgApi.appResourceTree.showTreeItemPicker( + SubscriptionTreeItem.contextValue, + context + ); + } - await SubscriptionTreeItem.createChild(context, node); + await SubscriptionTreeItem.createChild(context, node); } -export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await deleteDatabaseAccount(context, node, false) +export async function deleteAccount( + context: IActionContext, + node?: AzExtTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter, + ], + }); + } + + await deleteDatabaseAccount(context, node, false); } -export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { - const message = 'The connection string has been copied to the clipboard'; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); +export async function cosmosDBCopyConnectionString( + context: IActionContext, + node?: MongoAccountTreeItem | DocDBAccountTreeItemBase +): Promise { + const message = "The connection string has been copied to the clipboard"; + if (!node) { + node = await ext.rgApi.pickAppResource< + MongoAccountTreeItem | DocDBAccountTreeItemBase + >(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter, + ], + }); + } + + await vscode.env.clipboard.writeText(node.connectionString); + void vscode.window.showInformationMessage(message); } diff --git a/Source/extensionVariables.ts b/Source/extensionVariables.ts index 4a3fc2650..3af61432c 100644 --- a/Source/extensionVariables.ts +++ b/Source/extensionVariables.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeDataProvider, + AzExtTreeItem, + IAzExtOutputChannel, +} from "@microsoft/vscode-azext-utils"; import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { ExtensionContext, SecretStorage, TreeView } from "vscode"; import { DatabasesFileSystem } from "./DatabasesFileSystem"; @@ -19,33 +23,34 @@ import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWit * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts */ export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = 'azureDatabases'; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; + export let connectedMongoDB: MongoDatabaseTreeItem | undefined; + export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; + export let context: ExtensionContext; + export let outputChannel: IAzExtOutputChannel; + export let tree: AzExtTreeDataProvider; + export let treeView: TreeView; + export let attachedAccountsNode: AttachedAccountsTreeItem; + export let ignoreBundle: boolean | undefined; + export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; + export let secretStorage: SecretStorage; + export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; + export const prefix: string = "azureDatabases"; + export let fileSystem: DatabasesFileSystem; + export let mongoCodeLensProvider: MongoCodeLensProvider; + export let mongoLanguageClient: MongoDBLanguageClient; + export let rgApi: AzureHostExtensionApi; - export namespace settingsKeys { - export const mongoShellPath = 'mongo.shell.path'; - export const mongoShellArgs = 'mongo.shell.args'; - export const documentLabelFields = 'cosmosDB.documentLabelFields'; - export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; - export const mongoShellTimeout = 'mongo.shell.timeout'; - export const batchSize = 'azureDatabases.batchSize'; + export namespace settingsKeys { + export const mongoShellPath = "mongo.shell.path"; + export const mongoShellArgs = "mongo.shell.args"; + export const documentLabelFields = "cosmosDB.documentLabelFields"; + export const enableEndpointDiscovery = + "cosmosDB.enableEndpointDiscovery"; + export const mongoShellTimeout = "mongo.shell.timeout"; + export const batchSize = "azureDatabases.batchSize"; - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } + export namespace vsCode { + export const proxyStrictSSL = "http.proxyStrictSSL"; + } + } } diff --git a/Source/getExtensionApi.ts b/Source/getExtensionApi.ts index bfd553e74..63efdb7e5 100644 --- a/Source/getExtensionApi.ts +++ b/Source/getExtensionApi.ts @@ -8,24 +8,35 @@ import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { Extension, extensions } from "vscode"; import { localize } from "./utils/localize"; -export async function getApiExport(extensionId: string): Promise { - const extension: Extension | undefined = extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } +export async function getApiExport( + extensionId: string +): Promise { + const extension: Extension | undefined = + extensions.getExtension(extensionId); + if (extension) { + if (!extension.isActive) { + await extension.activate(); + } - return extension.exports; - } + return extension.exports; + } - return undefined; + return undefined; } export async function getResourceGroupsApi(): Promise { - const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); - if (rgApiProvider) { - return rgApiProvider.getApi('0.0.1'); - } else { - throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); - } + const rgApiProvider = + await getApiExport( + "ms-azuretools.vscode-azureresourcegroups" + ); + if (rgApiProvider) { + return rgApiProvider.getApi("0.0.1"); + } else { + throw new Error( + localize( + "noResourceGroupExt", + "Could not find the Azure Resource Groups extension" + ) + ); + } } diff --git a/Source/graph/gremlinEndpoints.ts b/Source/graph/gremlinEndpoints.ts index 1ef6b283d..0bbeae16f 100644 --- a/Source/graph/gremlinEndpoints.ts +++ b/Source/graph/gremlinEndpoints.ts @@ -3,35 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { nonNullValue } from '../utils/nonNull'; -import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { nonNullValue } from "../utils/nonNull"; +import { IGremlinEndpoint } from "../vscode-cosmosdbgraph.api"; -export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; +export async function tryGetGremlinEndpointFromAzure( + client: CosmosDBManagementClient, + resourceGroup: string, + account: string +): Promise { + // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk + const response = await client.databaseAccounts.get(resourceGroup, account); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const endpointUri = response.documentEndpoint; + // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint + return endpointUri ? parseEndpointUrl(endpointUri) : undefined; } -export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ +export function getPossibleGremlinEndpoints( + documentEndpoint: string +): IGremlinEndpoint[] { + // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - const documentSuffix = '.documents.azure.com'; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); + const documentSuffix = ".documents.azure.com"; + if (documentEndpoint.indexOf(documentSuffix) >= 0) { + // Pre-GA style (Dec 2017) + const preGAEndpoint = documentEndpoint.replace( + documentSuffix, + ".graphs.azure.com" + ); - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); + // Post-GA style (Dec 2017) + const postGAEndpoint = documentEndpoint.replace( + documentSuffix, + ".gremlin.cosmosdb.azure.com" + ); - return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } + return [ + parseEndpointUrl(postGAEndpoint), + parseEndpointUrl(preGAEndpoint), + ]; + } else { + console.warn(`Unexpected document URL format: ${documentEndpoint}`); + return [parseEndpointUrl(documentEndpoint)]; + } } /** @@ -39,9 +54,12 @@ export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinE * @param url An account URL such as 'https://.documents.azure.com:443/' */ function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; + const [, protocol, host, , portString] = nonNullValue( + url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), + "urlMatch" + ); + console.assert(!!protocol && !!host, "Unexpected endpoint format"); + const port = parseInt(portString || "443", 10); + console.assert(port > 0, "Unexpected port"); + return { host, port, ssl: protocol.toLowerCase() === "https" }; } diff --git a/Source/graph/registerGraphCommands.ts b/Source/graph/registerGraphCommands.ts index 1746c638b..21e05d9a5 100644 --- a/Source/graph/registerGraphCommands.ts +++ b/Source/graph/registerGraphCommands.ts @@ -3,60 +3,97 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; -import { ext } from '../extensionVariables'; +import { + AzExtTreeItem, + IActionContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; +import { cosmosGremlinFilter, doubleClickDebounceDelay } from "../constants"; +import { ext } from "../extensionVariables"; import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; import { GraphTreeItem } from "./tree/GraphTreeItem"; export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph(context, GraphTreeItem.contextValue); - } - await node.showExplorer(context); - }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createGraphDatabase", + createGraphDatabase + ); + registerCommandWithTreeNodeUnwrapping("cosmosDB.createGraph", createGraph); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteGraphDatabase", + async (context: IActionContext, node?: GraphDatabaseTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph( + context, + GraphDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteGraph", + async (context: IActionContext, node?: GraphCollectionTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph( + context, + GraphCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openGraphExplorer", + async (context: IActionContext, node: GraphTreeItem) => { + if (!node) { + node = await pickGraph( + context, + GraphTreeItem.contextValue + ); + } + await node.showExplorer(context); + }, + doubleClickDebounceDelay + ); } -export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); +export async function createGraphDatabase( + context: IActionContext, + node?: GraphAccountTreeItem +): Promise { + if (!node) { + node = await pickGraph(context); + } + await node.createChild(context); } -export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.createChild(context); +export async function createGraph( + context: IActionContext, + node?: GraphDatabaseTreeItem +): Promise { + if (!node) { + node = await pickGraph( + context, + GraphDatabaseTreeItem.contextValue + ); + } + await node.createChild(context); } -async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosGremlinFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickGraph( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [cosmosGremlinFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/graph/tree/GraphAccountTreeItem.ts b/Source/graph/tree/GraphAccountTreeItem.ts index 7e1f561fa..8025e4f8e 100644 --- a/Source/graph/tree/GraphAccountTreeItem.ts +++ b/Source/graph/tree/GraphAccountTreeItem.ts @@ -3,43 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { DatabaseDefinition, Resource } from "@azure/cosmos"; +import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; +import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; +import { GraphTreeItem } from "./GraphTreeItem"; export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBGraphAccount"; + public contextValue: string = GraphAccountTreeItem.contextValue; - constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + documentEndpoint: string, + private _gremlinEndpoint: IGremlinEndpoint | undefined, + masterKey: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super( + parent, + id, + label, + documentEndpoint, + masterKey, + isEmulator, + databaseAccount + ); + this.valuesToMask.push(documentEndpoint); + if (_gremlinEndpoint) { + this.valuesToMask.push(_gremlinEndpoint.host); + } + } - public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } + public initChild( + database: DatabaseDefinition & Resource + ): GraphDatabaseTreeItem { + return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case GraphDatabaseTreeItem.contextValue: + case GraphCollectionTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case GraphTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/graph/tree/GraphCollectionTreeItem.ts b/Source/graph/tree/GraphCollectionTreeItem.ts index 63709d977..efc25ae4c 100644 --- a/Source/graph/tree/GraphCollectionTreeItem.ts +++ b/Source/graph/tree/GraphCollectionTreeItem.ts @@ -3,85 +3,108 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; +import { + Container, + ContainerDefinition, + CosmosClient, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; +import { IDocDBTreeRoot } from "../../docdb/tree/IDocDBTreeRoot"; +import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; +import { GraphTreeItem } from "./GraphTreeItem"; export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - - } + public static contextValue: string = "cosmosDBGraph"; + public readonly contextValue: string = GraphCollectionTreeItem.contextValue; + public readonly parent: GraphDatabaseTreeItem; + + private readonly _graphTreeItem: GraphTreeItem; + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + private readonly _collection: ContainerDefinition & Resource; + + constructor( + parent: GraphDatabaseTreeItem, + collection: ContainerDefinition & Resource + ) { + super(parent); + this._collection = collection; + this._graphTreeItem = new GraphTreeItem(this, this._collection); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( + this + ); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return this._collection.id; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return [this._graphTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteGraphCollection" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public pickTreeItemImpl( + expectedContextValues: (string | RegExp)[] + ): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case GraphTreeItem.contextValue: + return this._graphTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getDatabaseClient(client).container(this.id); + } } diff --git a/Source/graph/tree/GraphDatabaseTreeItem.ts b/Source/graph/tree/GraphDatabaseTreeItem.ts index 1c5332700..4fc7a9655 100644 --- a/Source/graph/tree/GraphDatabaseTreeItem.ts +++ b/Source/graph/tree/GraphDatabaseTreeItem.ts @@ -3,63 +3,76 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; -import { GraphAccountTreeItem } from './GraphAccountTreeItem'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { + ContainerDefinition, + CosmosClient, + Database, + DatabaseDefinition, + Resource, +} from "@azure/cosmos"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; +import { getPossibleGremlinEndpoints } from "../gremlinEndpoints"; +import { GraphAccountTreeItem } from "./GraphAccountTreeItem"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Graph'; + public static contextValue: string = "cosmosDBGraphDatabase"; + public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Graph"; - constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { - super(parent, database); - } + constructor( + parent: GraphAccountTreeItem, + private _gremlinEndpoint: IGremlinEndpoint | undefined, + database: DatabaseDefinition & Resource + ) { + super(parent, database); + } - public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } + public initChild( + collection: ContainerDefinition & Resource + ): GraphCollectionTreeItem { + return new GraphCollectionTreeItem(this, collection); + } - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } + // Gremlin endpoint, if definitely known + get gremlinEndpoint(): IGremlinEndpoint | undefined { + return this._gremlinEndpoint; + } - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } + get possibleGremlinEndpoints(): IGremlinEndpoint[] { + return getPossibleGremlinEndpoints(this.root.endpoint); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } - } + protected override async getNewPartitionKey( + context: IActionContext + ): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: "Enter the partition key for the collection, or leave blank for fixed size.", + stepName: "partitionKeyForCollection", + validateInput: this.validatePartitionKey, + placeHolder: "e.g. /address", + }); - protected override async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address' - }); + if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { + partitionKey = "/" + partitionKey; + } - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } + return partitionKey; + } - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + if (/.+\//.test(key)) { + return "Cannot be a nested path"; + } + return undefined; + } } diff --git a/Source/graph/tree/GraphTreeItem.ts b/Source/graph/tree/GraphTreeItem.ts index 800fded5a..d98da8b6b 100644 --- a/Source/graph/tree/GraphTreeItem.ts +++ b/Source/graph/tree/GraphTreeItem.ts @@ -3,54 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { ContainerDefinition, Resource } from "@azure/cosmos"; +import { + AzExtTreeItem, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { localize } from "../../utils/localize"; +import { openUrl } from "../../utils/openUrl"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; -const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; +const alternativeGraphVisualizationToolsDocLink = + "https://aka.ms/cosmosdb-graph-alternative-tools"; export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this.commandId = 'cosmosDB.openGraphExplorer'; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } + public static contextValue: string = "cosmosDBGraphGraph"; + public readonly contextValue: string = GraphTreeItem.contextValue; + public readonly parent: GraphCollectionTreeItem; + public suppressMaskLabel = true; + + private readonly _collection: ContainerDefinition & Resource; + + constructor( + parent: GraphCollectionTreeItem, + collection: ContainerDefinition & Resource + ) { + super(parent); + this.commandId = "cosmosDB.openGraphExplorer"; + this._collection = collection; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return "Graph"; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public async showExplorer(_context: IActionContext): Promise { + const message: string = localize( + "mustInstallGraph", + "Cosmos DB Graph extension has been retired." + ); + const alternativeToolsOption = "Alternative Tools"; + const result = await vscode.window.showErrorMessage( + message, + alternativeToolsOption + ); + if (result === alternativeToolsOption) { + await openUrl(alternativeGraphVisualizationToolsDocLink); + } + } } diff --git a/Source/mongo/MongoCommand.ts b/Source/mongo/MongoCommand.ts index 79c33731f..ea9466b45 100644 --- a/Source/mongo/MongoCommand.ts +++ b/Source/mongo/MongoCommand.ts @@ -3,22 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RecognitionException } from 'antlr4ts'; -import * as vscode from 'vscode'; +import { RecognitionException } from "antlr4ts"; +import * as vscode from "vscode"; export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; + range: vscode.Range; + text: string; + collection?: string; + name?: string; + arguments?: string[]; + argumentObjects?: Object[]; + errors?: ErrorDescription[]; + chained?: boolean; } export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; + range: vscode.Range; + message: string; + exception?: RecognitionException; } diff --git a/Source/mongo/MongoScrapbook.ts b/Source/mongo/MongoScrapbook.ts index d5dfe6d00..2f441285e 100644 --- a/Source/mongo/MongoScrapbook.ts +++ b/Source/mongo/MongoScrapbook.ts @@ -3,489 +3,718 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ObjectID } from 'bson'; -import { Collection } from 'mongodb'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { filterType, findType } from '../utils/array'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { mongoLexer } from './grammar/mongoLexer'; -import * as mongoParser from './grammar/mongoParser'; -import { MongoVisitor } from './grammar/visitors'; -import { ErrorDescription, MongoCommand } from './MongoCommand'; -import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; -import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; +import { + IActionContext, + IParsedError, + openReadOnlyContent, + parseError, + ReadOnlyContent, +} from "@microsoft/vscode-azext-utils"; +import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; +import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { ObjectID } from "bson"; +import { Collection } from "mongodb"; +import { EOL } from "os"; +import * as vscode from "vscode"; +import { ext } from "../extensionVariables"; +import { filterType, findType } from "../utils/array"; +import { localize } from "../utils/localize"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { LexerErrorListener, ParserErrorListener } from "./errorListeners"; +import { mongoLexer } from "./grammar/mongoLexer"; +import * as mongoParser from "./grammar/mongoParser"; +import { MongoVisitor } from "./grammar/visitors"; +import { ErrorDescription, MongoCommand } from "./MongoCommand"; +import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; +import { + MongoDatabaseTreeItem, + stripQuotes, +} from "./tree/MongoDatabaseTreeItem"; +import { + IMongoDocument, + MongoDocumentTreeItem, +} from "./tree/MongoDocumentTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); -const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of (command.errors || [])) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; +const notInScrapbookMessage = + "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; + +export function getAllErrorsFromTextDocument( + document: vscode.TextDocument +): vscode.Diagnostic[] { + const commands = getAllCommandsFromTextDocument(document); + const errors: vscode.Diagnostic[] = []; + for (const command of commands) { + for (const error of command.errors || []) { + const diagnostic = new vscode.Diagnostic( + error.range, + error.message + ); + errors.push(diagnostic); + } + } + + return errors; } -export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); +export async function executeAllCommandsFromActiveEditor( + context: IActionContext +): Promise { + ext.outputChannel.appendLog("Executing all commands in scrapbook..."); + const commands = getAllCommandsFromActiveEditor(); + await executeCommands(context, commands); } -export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); - return await executeCommand(context, command); +export async function executeCommandFromActiveEditor( + context: IActionContext, + position?: vscode.Position +): Promise { + const commands = getAllCommandsFromActiveEditor(); + const command = findCommandAtPosition( + commands, + position || vscode.window.activeTextEditor?.selection.start + ); + return await executeCommand(context, command); } function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } + const activeEditor = vscode.window.activeTextEditor; + if (activeEditor) { + return getAllCommandsFromTextDocument(activeEditor.document); + } else { + // Shouldn't be able to reach this + throw new Error(notInScrapbookMessage); + } } -export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { - return getAllCommandsFromText(document.getText()); +export function getAllCommandsFromTextDocument( + document: vscode.TextDocument +): MongoCommand[] { + return getAllCommandsFromText(document.getText()); } -async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { - const label: string = 'Scrapbook-execute-all-results'; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } +async function executeCommands( + context: IActionContext, + commands: MongoCommand[] +): Promise { + const label: string = "Scrapbook-execute-all-results"; + const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; + const readOnlyContent: ReadOnlyContent = await openReadOnlyContent( + { label, fullId }, + "", + ".txt", + { viewColumn: vscode.ViewColumn.Beside } + ); + + for (const command of commands) { + try { + await executeCommand(context, command, readOnlyContent); + } catch (e) { + const err = parseError(e); + if (err.isUserCancelledError) { + throw e; + } else { + const message = `${command.text.split("(")[0]} at ${ + command.range.start.line + 1 + }:${command.range.start.character + 1}: ${err.message}`; + throw new Error(message); + } + } + } } -async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === 'find' && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, 'collection'); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); - await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === 'findOne') { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp(command, 'collection'); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); - if (!colNode) { - throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = 'Scrapbook-results'; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error('No MongoDB command found at the current cursor location.'); - } +async function executeCommand( + context: IActionContext, + command: MongoCommand, + readOnlyContent?: ReadOnlyContent +): Promise { + if (command) { + try { + context.telemetry.properties.command = command.name; + context.telemetry.properties.argsCount = String( + command.arguments ? command.arguments.length : 0 + ); + } catch (error) { + // Ignore + } + + const database = ext.connectedMongoDB; + if (!database) { + throw new Error( + 'Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item' + ); + } + if (command.errors && command.errors.length > 0) { + //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. + const err = command.errors[0]; + throw new Error( + localize( + "unableToParseSyntax", + `Unable to parse syntax. Error near line ${ + err.range.start.line + 1 + }, column ${err.range.start.character + 1}: "${ + err.message + }"` + ) + ); + } + + // we don't handle chained commands so we can only handle "find" if isn't chained + if (command.name === "find" && !command.chained) { + const db = await database.connectToDb(); + const collectionName: string = nonNullProp(command, "collection"); + const collection: Collection = db.collection(collectionName); + // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because + // the executed 'find' command could have a filter or projection that is not handled by a cached tree node + const node = new MongoCollectionTreeItem( + database, + collection, + command.argumentObjects + ); + await ext.fileSystem.showTextDocument(node, { + viewColumn: vscode.ViewColumn.Beside, + }); + } else { + const result = await database.executeCommand(command, context); + if (command.name === "findOne") { + if (result === "null") { + throw new Error(`Could not find any documents`); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const document: IMongoDocument = EJSON.parse(result); + const collectionName: string = nonNullProp( + command, + "collection" + ); + + const collectionId: string = `${database.fullId}/${collectionName}`; + const colNode: MongoCollectionTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + collectionId, + context + ); + if (!colNode) { + throw new Error( + localize( + "failedToFind", + 'Failed to find collection "{0}".', + collectionName + ) + ); + } + const docNode = new MongoDocumentTreeItem(colNode, document); + await ext.fileSystem.showTextDocument(docNode, { + viewColumn: vscode.ViewColumn.Beside, + }); + } else { + if (readOnlyContent) { + await readOnlyContent.append(`${result}${EOL}${EOL}`); + } else { + const label: string = "Scrapbook-results"; + const fullId: string = `${database.fullId}/${label}`; + await openReadOnlyContent( + { label, fullId }, + result, + ".json", + { viewColumn: vscode.ViewColumn.Beside } + ); + } + + await refreshTreeAfterCommand(database, command, context); + } + } + } else { + throw new Error( + "No MongoDB command found at the current cursor location." + ); + } } -async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { - if (command.name === 'drop') { - await database.refresh(context); - } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); - if (collectionNode) { - await collectionNode.refresh(context); - } - } +async function refreshTreeAfterCommand( + database: MongoDatabaseTreeItem, + command: MongoCommand, + context: IActionContext +): Promise { + if (command.name === "drop") { + await database.refresh(context); + } else if ( + command.collection && + command.name && + /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test( + command.name + ) + ) { + const collectionNode = await ext.rgApi.appResourceTree.findTreeItem( + database.fullId + "/" + command.collection, + context + ); + if (collectionNode) { + await collectionNode.refresh(context); + } + } } export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "" - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; + const lexer = new mongoLexer(new InputStream(content)); + const lexerListener = new LexerErrorListener(); + lexer.removeErrorListeners(); // Default listener outputs to the console + lexer.addErrorListener(lexerListener); + const tokens: CommonTokenStream = new CommonTokenStream(lexer); + + const parser = new mongoParser.mongoParser(tokens); + const parserListener = new ParserErrorListener(); + parser.removeErrorListeners(); // Default listener outputs to the console + parser.addErrorListener(parserListener); + + const commandsContext: mongoParser.MongoCommandsContext = + parser.mongoCommands(); + const commands = new FindMongoCommandsVisitor().visit(commandsContext); + + // Match errors with commands based on location + const errors = lexerListener.errors.concat(parserListener.errors); + errors.sort((a, b) => { + const linediff = a.range.start.line - b.range.start.line; + const chardiff = a.range.start.character - b.range.start.character; + return linediff || chardiff; + }); + for (const err of errors) { + const associatedCommand = findCommandAtPosition( + commands, + err.range.start + ); + if (associatedCommand) { + associatedCommand.errors = associatedCommand.errors || []; + associatedCommand.errors.push(err); + } else { + // Create a new command to hook this up to + const emptyCommand: MongoCommand = { + collection: undefined, + name: undefined, + range: err.range, + text: "", + }; + emptyCommand.errors = [err]; + commands.push(emptyCommand); + } + } + + return commands; } -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; +export function findCommandAtPosition( + commands: MongoCommand[], + position?: vscode.Position +): MongoCommand { + let lastCommandOnSameLine: MongoCommand | undefined; + let lastCommandBeforePosition: MongoCommand | undefined; + if (position) { + for (const command of commands) { + if (command.range.contains(position)) { + return command; + } + if (command.range.end.line === position.line) { + lastCommandOnSameLine = command; + } + if (command.range.end.isBefore(position)) { + lastCommandBeforePosition = command; + } + } + } + return ( + lastCommandOnSameLine || + lastCommandBeforePosition || + commands[commands.length - 1] + ); } class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop'); - this.commands.push({ - range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); - return {}; - } - } - - private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' - this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); - if (argumentContextArray.length > 1) { - this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); - return {}; - } - } - - private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { - if (!tokenText) { // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop'); - const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* + private commands: MongoCommand[] = []; + + public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { + const funcCallCount: number = filterType( + ctx.children, + mongoParser.FunctionCallContext + ).length; + const stop = nonNullProp(ctx, "stop"); + this.commands.push({ + range: new vscode.Range( + ctx.start.line - 1, + ctx.start.charPositionInLine, + stop.line - 1, + stop.charPositionInLine + ), + text: ctx.text, + name: "", + arguments: [], + argumentObjects: [], + chained: funcCallCount > 1 ? true : false, + }); + return super.visitCommand(ctx); + } + + public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { + this.commands[this.commands.length - 1].collection = ctx.text; + return super.visitCollection(ctx); + } + + public visitFunctionCall( + ctx: mongoParser.FunctionCallContext + ): MongoCommand[] { + if (ctx.parent instanceof mongoParser.CommandContext) { + this.commands[this.commands.length - 1].name = + (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; + } + return super.visitFunctionCall(ctx); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { + try { + const argumentsContext = ctx.parent; + if (argumentsContext) { + const functionCallContext = argumentsContext.parent; + if ( + functionCallContext && + functionCallContext.parent instanceof + mongoParser.CommandContext + ) { + const lastCommand = this.commands[this.commands.length - 1]; + const argAsObject = this.contextToObject(ctx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const argText = EJSON.stringify(argAsObject); + nonNullProp(lastCommand, "arguments").push(argText); + const escapeHandled = + this.deduplicateEscapesForRegex(argText); + let ejsonParsed = {}; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + ejsonParsed = EJSON.parse(escapeHandled); + } catch (error) { + //EJSON parse failed due to a wrong flag, etc. + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + nonNullProp(lastCommand, "argumentObjects").push( + ejsonParsed + ); + } + } + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + return super.visitArgument(ctx); + } + + protected defaultResult(_node: ParseTree): MongoCommand[] { + return this.commands; + } + + private contextToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + if (!ctx || ctx.childCount === 0) { + //Base case and malformed statements + return {}; + } + // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 + const child: ParseTree = nonNullProp(ctx, "children")[0]; + if (child instanceof mongoParser.LiteralContext) { + return this.literalContextToObject(child, ctx); + } else if (child instanceof mongoParser.ObjectLiteralContext) { + return this.objectLiteralContextToObject(child); + } else if (child instanceof mongoParser.ArrayLiteralContext) { + return this.arrayLiteralContextToObject(child); + } else if (child instanceof mongoParser.FunctionCallContext) { + return this.functionCallContextToObject(child, ctx); + } else if (child instanceof ErrorNode) { + return {}; + } else { + this.addErrorToCommand( + `Unrecognized node type encountered. We could not parse ${child.text}`, + ctx + ); + return {}; + } + } + + private literalContextToObject( + child: mongoParser.LiteralContext, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + const text = child.text; + const tokenType = child.start.type; + const nonStringLiterals = [ + mongoParser.mongoParser.NullLiteral, + mongoParser.mongoParser.BooleanLiteral, + mongoParser.mongoParser.NumericLiteral, + ]; + if (tokenType === mongoParser.mongoParser.StringLiteral) { + return stripQuotes(text); + } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { + return this.regexLiteralContextToObject(ctx, text); + } else if (nonStringLiterals.indexOf(tokenType) > -1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return JSON.parse(text); + } else { + this.addErrorToCommand( + `Unrecognized token. Token text: ${text}`, + ctx + ); + return {}; + } + } + + private objectLiteralContextToObject( + child: mongoParser.ObjectLiteralContext + ): Object { + const propertyNameAndValue = findType( + child.children, + mongoParser.PropertyNameAndValueListContext + ); + if (!propertyNameAndValue) { + // Argument is {} + return {}; + } else { + const parsedObject: Object = {}; + const propertyAssignments = filterType( + propertyNameAndValue.children, + mongoParser.PropertyAssignmentContext + ); + for (const propertyAssignment of propertyAssignments) { + const propertyAssignmentChildren = nonNullProp( + propertyAssignment, + "children" + ); + const propertyName = ( + propertyAssignmentChildren[0] + ); + const propertyValue = ( + propertyAssignmentChildren[2] + ); + parsedObject[stripQuotes(propertyName.text)] = + this.contextToObject(propertyValue); + } + return parsedObject; + } + } + + private arrayLiteralContextToObject( + child: mongoParser.ArrayLiteralContext + ) { + const elementList = findType( + child.children, + mongoParser.ElementListContext + ); + if (elementList) { + const elementItems = filterType( + elementList.children, + mongoParser.PropertyValueContext + ); + return elementItems.map(this.contextToObject.bind(this)); + } else { + return []; + } + } + + private functionCallContextToObject( + child: mongoParser.FunctionCallContext, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + const functionTokens = child.children; + const constructorCall: TerminalNode = nonNullValue( + findType(functionTokens, TerminalNode), + "constructorCall" + ); + const argumentsToken: mongoParser.ArgumentsContext = nonNullValue( + findType(functionTokens, mongoParser.ArgumentsContext), + "argumentsToken" + ); + if ( + !( + argumentsToken._CLOSED_PARENTHESIS && + argumentsToken._OPEN_PARENTHESIS + ) + ) { + //argumentsToken does not have '(' or ')' + this.addErrorToCommand( + `Expecting parentheses or quotes at '${constructorCall.text}'`, + ctx + ); + return {}; + } + + const argumentContextArray: mongoParser.ArgumentContext[] = filterType( + argumentsToken.children, + mongoParser.ArgumentContext + ); + if (argumentContextArray.length > 1) { + this.addErrorToCommand( + `Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, + ctx + ); + return {}; + } + + const tokenText: string | undefined = argumentContextArray.length + ? argumentContextArray[0].text + : undefined; + switch (constructorCall.text) { + case "ObjectId": + return this.objectIdToObject(ctx, tokenText); + case "ISODate": + return this.isodateToObject(ctx, tokenText); + case "Date": + return this.dateToObject(ctx, tokenText); + default: + this.addErrorToCommand( + `Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, + ctx + ); + return {}; + } + } + + private dateToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText); + if (date instanceof Date) { + return { $date: date.toString() }; + } else { + return date; + } + } + + private isodateToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); + + if (date instanceof Date) { + return { $date: date.toISOString() }; + } else { + return date; + } + } + + private tryToConstructDate( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string, + isIsodate: boolean = false + ): Date | {} { + if (!tokenText) { + // usage : ObjectID() + return new Date(); + } else { + try { + tokenText = stripQuotes(tokenText); + + // if the tokenText was an isodate, the last char must be Z + if (isIsodate) { + if (tokenText[tokenText.length - 1] !== "Z") { + tokenText += "Z"; + } + } + + return new Date(tokenText); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + } + + private objectIdToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): Object { + let hexID: string; + let constructedObject: ObjectID; + if (!tokenText) { + // usage : ObjectID() + constructedObject = new ObjectID(); + } else { + hexID = stripQuotes(tokenText); + try { + constructedObject = new ObjectID(hexID); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + return { $oid: constructedObject.toString() }; + } + + private regexLiteralContextToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + text: string + ): Object { + const separator = text.lastIndexOf("/"); + const flags = + separator !== text.length - 1 ? text.substring(separator + 1) : ""; + const pattern = text.substring(1, separator); + try { + // validate the pattern and flags. + // It is intended for the errors thrown here to be handled by the catch block. + let tokenObject = new RegExp(pattern, flags); + // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars + tokenObject = tokenObject; + // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax + return { + $regex: this.regexToStringNotation(pattern), + $options: flags, + }; + } catch (error) { + //User may not have finished typing + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + + private addErrorToCommand( + errorMessage: string, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): void { + const command = this.commands[this.commands.length - 1]; + command.errors = command.errors || []; + const stop = nonNullProp(ctx, "stop"); + const currentErrorDesc: ErrorDescription = { + message: errorMessage, + range: new vscode.Range( + ctx.start.line - 1, + ctx.start.charPositionInLine, + stop.line - 1, + stop.charPositionInLine + ), + }; + command.errors.push(currentErrorDesc); + } + + private regexToStringNotation(pattern: string): string { + // The equivalence: + // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" + return pattern.replace(/\\([0-9a-z.*])/i, "\\\\$1"); + } + + private deduplicateEscapesForRegex(argAsString: string): string { + const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; + /* We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } - + return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); + } } diff --git a/Source/mongo/MongoShell.ts b/Source/mongo/MongoShell.ts index b8f982ee8..81784f2af 100644 --- a/Source/mongo/MongoShell.ts +++ b/Source/mongo/MongoShell.ts @@ -3,185 +3,216 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; -import { randomUtils } from '../utils/randomUtils'; -import { getBatchSizeSetting } from '../utils/workspacUtils'; -import { wrapError } from '../utils/wrapError'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as os from "os"; +import * as vscode from "vscode"; +import { InteractiveChildProcess } from "../utils/InteractiveChildProcess"; +import { randomUtils } from "../utils/randomUtils"; +import { getBatchSizeSetting } from "../utils/workspacUtils"; +import { wrapError } from "../utils/wrapError"; -const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; +const timeoutMessage = + "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = '(More)'; +const extensionMoreMessage = "(More)"; -const sentinelBase = 'EXECUTION COMPLETED'; +const sentinelBase = "EXECUTION COMPLETED"; const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } +function createSentinel(): string { + return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; +} export class MongoShell extends vscode.Disposable { - - constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { - super(() => this.dispose()); - } - - public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '' - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut(text => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); - - resolve(stdOutNoSentinel); - } - })); - disposables.push( - this._process.onStdErr(text => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - })); - disposables.push( - this._process.onError(error => { - reject(error); - })); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error("The process exited prematurely."); - } - - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } - finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } + constructor( + private _process: InteractiveChildProcess, + private _timeoutSeconds: number + ) { + super(() => this.dispose()); + } + + public static async create( + execPath: string, + execArgs: string[], + connectionString: string, + isEmulator: boolean | undefined, + outputChannel: vscode.OutputChannel, + timeoutSeconds: number + ): Promise { + try { + const args: string[] = execArgs.slice() || []; // Snapshot since we modify it + args.push(connectionString); + + if (isEmulator) { + // Without these the connection will fail due to the self-signed DocDB certificate + if (args.indexOf("--ssl") < 0) { + args.push("--ssl"); + } + if (args.indexOf("--sslAllowInvalidCertificates") < 0) { + args.push("--sslAllowInvalidCertificates"); + } + } + + const process: InteractiveChildProcess = + await InteractiveChildProcess.create({ + outputChannel: outputChannel, + command: execPath, + args, + outputFilterSearch: sentinelRegex, + outputFilterReplace: "", + }); + const shell: MongoShell = new MongoShell(process, timeoutSeconds); + + // Try writing an empty script to verify the process is running correctly and allow us + // to catch any errors related to the start-up of the process before trying to write to it. + await shell.executeScript(""); + + // Configure the batch size + await shell.executeScript( + `DBQuery.shellBatchSize = ${getBatchSizeSetting()}` + ); + + return shell; + } catch (error) { + throw wrapCheckOutputWindow(error); + } + } + + public dispose(): void { + this._process.kill(); + } + + public async useDatabase(database: string): Promise { + return await this.executeScript(`use ${database}`); + } + + public async executeScript(script: string): Promise { + script = convertToSingleLine(script); + + let stdOut = ""; + const sentinel = createSentinel(); + + const disposables: vscode.Disposable[] = []; + try { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + const result = await new Promise( + async (resolve, reject) => { + try { + startScriptTimeout(this._timeoutSeconds, reject); + + // Hook up events + disposables.push( + this._process.onStdOut((text) => { + stdOut += text; + // eslint-disable-next-line prefer-const + let { text: stdOutNoSentinel, removed } = + removeSentinel(stdOut, sentinel); + if (removed) { + // The sentinel was found, which means we are done. + + // Change the "type 'it' for more" message to one that doesn't ask users to type anything, + // since we're not currently interactive like that. + // CONSIDER: Ideally we would allow users to click a button to iterate through more data, + // or even just do it for them + stdOutNoSentinel = stdOutNoSentinel.replace( + mongoShellMoreMessage, + extensionMoreMessage + ); + + resolve(stdOutNoSentinel); + } + }) + ); + disposables.push( + this._process.onStdErr((text) => { + // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. + // So consider this an error. + // (It's okay if we fire this multiple times, the first one wins.) + reject(wrapCheckOutputWindow(text.trim())); + }) + ); + disposables.push( + this._process.onError((error) => { + reject(error); + }) + ); + + // Write the script to STDIN + if (script) { + this._process.writeLine(script); + } + + // Mark end of result by sending the sentinel wrapped in quotes so the console will spit + // it back out as a string value after it's done processing the script + const quotedSentinel = `"${sentinel}"`; + this._process.writeLine(quotedSentinel); // (Don't display the sentinel) + } catch (error) { + // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it + + if ((<{ code?: string }>error).code === "EPIPE") { + // Give a chance for start-up errors to show up before rejecting with this more general error message + await delay(500); + // eslint-disable-next-line no-ex-assign + error = new Error( + "The process exited prematurely." + ); + } + + reject(wrapCheckOutputWindow(error)); + } + } + ); + + return result.trim(); + } finally { + // Dispose event handlers + for (const d of disposables) { + d.dispose(); + } + } + } } -function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout( - () => { - reject(timeoutMessage); - }, - timeoutSeconds * 1000); - } +function startScriptTimeout( + timeoutSeconds: number | 0, + reject: (err: unknown) => void +): void { + if (timeoutSeconds > 0) { + setTimeout(() => { + reject(timeoutMessage); + }, timeoutSeconds * 1000); + } } function convertToSingleLine(script: string): string { - return script.split(os.EOL) - .map(line => line.trim()) - .join(''); - + return script + .split(os.EOL) + .map((line) => line.trim()) + .join(""); } -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } +function removeSentinel( + text: string, + sentinel: string +): { text: string; removed: boolean } { + const index = text.indexOf(sentinel); + if (index >= 0) { + return { text: text.slice(0, index), removed: true }; + } else { + return { text, removed: false }; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); + const checkOutputMsg = + "The output window may contain additional information."; + return parseError(error).message.includes(checkOutputMsg) + ? error + : wrapError(error, checkOutputMsg); } diff --git a/Source/mongo/connectToMongoClient.ts b/Source/mongo/connectToMongoClient.ts index 88aa2df17..e2fe8d5d1 100644 --- a/Source/mongo/connectToMongoClient.ts +++ b/Source/mongo/connectToMongoClient.ts @@ -3,47 +3,58 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MongoClient, MongoClientOptions } from 'mongodb'; -import { emulatorPassword, Links } from '../constants'; - -export async function connectToMongoClient(connectionString: string, appName: string): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string, name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - throw error; - } +import { MongoClient, MongoClientOptions } from "mongodb"; +import { emulatorPassword, Links } from "../constants"; + +export async function connectToMongoClient( + connectionString: string, + appName: string +): Promise { + // appname appears to be the correct equivalent to user-agent for mongo + const options: MongoClientOptions = { + // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string + appName: `@${appName}@`, + // https://github.com/lmammino/mongo-uri-builder/issues/2 + useNewUrlParser: true, + useUnifiedTopology: true, + }; + + if (isCosmosEmulatorConnectionString(connectionString)) { + // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 + options.tlsAllowInvalidCertificates = true; + } + + try { + return await MongoClient.connect(connectionString, options); + } catch (err) { + // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info + const error = <{ message?: string; name?: string }>err; + const message = error && error.message; + + // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" + // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" + if ( + message && + /ECONNREFUSED/.test(message) && + /(localhost|127\.0\.0\.1)/.test(message) + ) { + throw new MongoConnectError(); + } + + throw error; + } } export class MongoConnectError extends Error { - constructor() { - super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); - } + constructor() { + super( + `Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.` + ); + } } -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); +export function isCosmosEmulatorConnectionString( + connectionString: string +): boolean { + return connectionString.includes(encodeURIComponent(emulatorPassword)); } diff --git a/Source/mongo/errorListeners.ts b/Source/mongo/errorListeners.ts index ea582d544..00d510cd5 100644 --- a/Source/mongo/errorListeners.ts +++ b/Source/mongo/errorListeners.ts @@ -3,65 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { Recognizer } from 'antlr4ts/Recognizer'; -import { Token } from 'antlr4ts/Token'; +import { ANTLRErrorListener } from "antlr4ts/ANTLRErrorListener"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { Recognizer } from "antlr4ts/Recognizer"; +import { Token } from "antlr4ts/Token"; import * as vscode from "vscode"; -import { ErrorDescription } from './MongoCommand'; +import { ErrorDescription } from "./MongoCommand"; export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; - public get errors(): ErrorDescription[] { - return this._errors; - } + public get errors(): ErrorDescription[] { + return this._errors; + } - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: Token | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e, + }; + this._errors.push(error); + } } export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } + private _errors: ErrorDescription[] = []; - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { + public get errors(): ErrorDescription[] { + return this._errors; + } - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: number | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e, + }; + this._errors.push(error); + } } diff --git a/Source/mongo/grammar/mongoLexer.ts b/Source/mongo/grammar/mongoLexer.ts index 3b6cbbdd0..47b461a6f 100644 --- a/Source/mongo/grammar/mongoLexer.ts +++ b/Source/mongo/grammar/mongoLexer.ts @@ -9,239 +9,312 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { RuleContext } from 'antlr4ts/RuleContext'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; +import { CharStream } from "antlr4ts/CharStream"; +import { NotNull, Override } from "antlr4ts/Decorators"; +import { Lexer } from "antlr4ts/Lexer"; +import * as Utils from "antlr4ts/misc/Utils"; +import { RuleContext } from "antlr4ts/RuleContext"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +export class mongoLexer extends Lexer { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly modeNames: string[] = ["DEFAULT_MODE"]; + public static readonly ruleNames: string[] = [ + "T__0", + "T__1", + "T__2", + "T__3", + "T__4", + "T__5", + "T__6", + "T__7", + "RegexLiteral", + "RegexFlag", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "STRING_ESCAPE", + "DecimalIntegerLiteral", + "ExponentPart", + "DecimalDigit", + "WHITESPACE", + ]; -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = [ - "DEFAULT_MODE" - ]; - - public static readonly ruleNames: string[] = [ - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", - "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", - "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", - "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", - "ExponentPart", "DecimalDigit", "WHITESPACE" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoLexer.ruleNames; } - - @Override - public get serializedATN(): string { return mongoLexer._serializedATN; } - - @Override - public get modeNames(): string[] { return mongoLexer.modeNames; } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text) - ; - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, + "'('", + "','", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "':'", + undefined, + undefined, + undefined, + undefined, + "'null'", + undefined, + undefined, + undefined, + undefined, + "';'", + "'.'", + "'db'", + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + "RegexLiteral", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "WHITESPACE", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( + mongoLexer._LITERAL_NAMES, + mongoLexer._SYMBOLIC_NAMES, + [] + ); -} + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoLexer.VOCABULARY; + } + + private isExternalIdentifierText(text) { + return text === "db"; + } + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(mongoLexer._ATN, this); + } + + @Override + public get grammarFileName(): string { + return "mongo.g4"; + } + @Override + public get ruleNames(): string[] { + return mongoLexer.ruleNames; + } + + @Override + public get serializedATN(): string { + return mongoLexer._serializedATN; + } + + @Override + public get modeNames(): string[] { + return mongoLexer.modeNames; + } + + @Override + public sempred( + _localctx: RuleContext, + ruleIndex: number, + predIndex: number + ): boolean { + switch (ruleIndex) { + case 21: + return this.IDENTIFIER_sempred(_localctx, predIndex); + } + return true; + } + private IDENTIFIER_sempred( + _localctx: RuleContext, + predIndex: number + ): boolean { + switch (predIndex) { + case 0: + return !this.isExternalIdentifierText(this.text); + } + return true; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + + "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + + "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + + "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + + "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + + "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + + "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + + "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + + "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + + "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + + "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + + "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + + "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + + "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + + "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + + "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + + "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + + "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + + "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + + "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + + "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + + "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + + "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + + "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + + "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + + "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" + + "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + + "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + + 'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' + + "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + + 'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' + + "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + + "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + + "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + + "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + + "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + + "\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + + "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + + ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + + "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + + "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + + "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + + "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + + "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" + + "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + + "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + + "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + + "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + + "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + + "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + + "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + + "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + + "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + + "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + + "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + + "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + + "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + + "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + + "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + + "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + + "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + + "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + + "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + + "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + + "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + + "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + + "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + + "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + + "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + + "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + + "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + + "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + + '\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' + + "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + + "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + + "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + + "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + + "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + + "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + + "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + + "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + + "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + + "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + + "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + + "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + + "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + + "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + + "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + + "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + + "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + + "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + + "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + + "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + + "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + + "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + + "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + + "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + + "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + + "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + + "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + + "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + + "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + + "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + + "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + + "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + + "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + + "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + + "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + + "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + + "\x04\x02\x03\x02\b\x02\x02"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoLexer.__ATN) { + mongoLexer.__ATN = new ATNDeserializer().deserialize( + Utils.toCharArray(mongoLexer._serializedATN) + ); + } + + return mongoLexer.__ATN; + } +} diff --git a/Source/mongo/grammar/mongoListener.ts b/Source/mongo/grammar/mongoListener.ts index 43514f500..d1d8ffac8 100644 --- a/Source/mongo/grammar/mongoListener.ts +++ b/Source/mongo/grammar/mongoListener.ts @@ -1,17 +1,30 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - - -import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { + ArgumentContext, + ArgumentsContext, + ArrayLiteralContext, + CollectionContext, + CommandContext, + CommandsContext, + CommentContext, + ElementListContext, + EmptyCommandContext, + FunctionCallContext, + LiteralContext, + MongoCommandsContext, + ObjectLiteralContext, + PropertyAssignmentContext, + PropertyNameAndValueListContext, + PropertyNameContext, + PropertyValueContext, +} from "./mongoParser"; /** * This interface defines a complete listener for a parse tree produced by @@ -143,12 +156,16 @@ export interface mongoListener extends ParseTreeListener { * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; + enterPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => void; /** * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; + exitPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => void; /** * Enter a parse tree produced by `mongoParser.propertyAssignment`. @@ -205,4 +222,3 @@ export interface mongoListener extends ParseTreeListener { */ exitComment?: (ctx: CommentContext) => void; } - diff --git a/Source/mongo/grammar/mongoParser.ts b/Source/mongo/grammar/mongoParser.ts index c1d38f4d0..f08e3ff51 100644 --- a/Source/mongo/grammar/mongoParser.ts +++ b/Source/mongo/grammar/mongoParser.ts @@ -9,1458 +9,1650 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { TokenStream } from 'antlr4ts/TokenStream'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { mongoListener } from './mongoListener'; -import { mongoVisitor } from './mongoVisitor'; - - - +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; +import { NotNull, Override } from "antlr4ts/Decorators"; +import * as Utils from "antlr4ts/misc/Utils"; +import { NoViableAltException } from "antlr4ts/NoViableAltException"; +import { Parser } from "antlr4ts/Parser"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { RuleVersion } from "antlr4ts/RuleVersion"; +import { Token } from "antlr4ts/Token"; +import { TokenStream } from "antlr4ts/TokenStream"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +import { mongoListener } from "./mongoListener"; +import { mongoVisitor } from "./mongoVisitor"; export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", "commands", "command", "emptyCommand", "collection", - "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", - "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", - "literal", "propertyName", "comment" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoParser.ruleNames; } - - @Override - public get serializedATN(): string { return mongoParser._serializedATN; } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + - "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } - + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly RULE_mongoCommands = 0; + public static readonly RULE_commands = 1; + public static readonly RULE_command = 2; + public static readonly RULE_emptyCommand = 3; + public static readonly RULE_collection = 4; + public static readonly RULE_functionCall = 5; + public static readonly RULE_arguments = 6; + public static readonly RULE_argument = 7; + public static readonly RULE_objectLiteral = 8; + public static readonly RULE_arrayLiteral = 9; + public static readonly RULE_elementList = 10; + public static readonly RULE_propertyNameAndValueList = 11; + public static readonly RULE_propertyAssignment = 12; + public static readonly RULE_propertyValue = 13; + public static readonly RULE_literal = 14; + public static readonly RULE_propertyName = 15; + public static readonly RULE_comment = 16; + public static readonly ruleNames: string[] = [ + "mongoCommands", + "commands", + "command", + "emptyCommand", + "collection", + "functionCall", + "arguments", + "argument", + "objectLiteral", + "arrayLiteral", + "elementList", + "propertyNameAndValueList", + "propertyAssignment", + "propertyValue", + "literal", + "propertyName", + "comment", + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, + "'('", + "','", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "':'", + undefined, + undefined, + undefined, + undefined, + "'null'", + undefined, + undefined, + undefined, + undefined, + "';'", + "'.'", + "'db'", + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + "RegexLiteral", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "WHITESPACE", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( + mongoParser._LITERAL_NAMES, + mongoParser._SYMBOLIC_NAMES, + [] + ); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoParser.VOCABULARY; + } + + @Override + public get grammarFileName(): string { + return "mongo.g4"; + } + + @Override + public get ruleNames(): string[] { + return mongoParser.ruleNames; + } + + @Override + public get serializedATN(): string { + return mongoParser._serializedATN; + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(mongoParser._ATN, this); + } + @RuleVersion(0) + public mongoCommands(): MongoCommandsContext { + const _localctx: MongoCommandsContext = new MongoCommandsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 34; + this.commands(); + this.state = 35; + this.match(mongoParser.EOF); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public commands(): CommandsContext { + const _localctx: CommandsContext = new CommandsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 2, mongoParser.RULE_commands); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 42; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.SingleLineComment) | + (1 << mongoParser.MultiLineComment) | + (1 << mongoParser.SEMICOLON) | + (1 << mongoParser.DB))) !== + 0 + ) { + { + this.state = 40; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.DB: + { + this.state = 37; + this.command(); + } + break; + case mongoParser.SEMICOLON: + { + this.state = 38; + this.emptyCommand(); + } + break; + case mongoParser.SingleLineComment: + case mongoParser.MultiLineComment: + { + this.state = 39; + this.comment(); + } + break; + default: + throw new NoViableAltException(this); + } + } + this.state = 44; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public command(): CommandContext { + const _localctx: CommandContext = new CommandContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 4, mongoParser.RULE_command); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 45; + this.match(mongoParser.DB); + this.state = 48; + this._errHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this._input, 2, this._ctx) + ) { + case 1: + { + this.state = 46; + this.match(mongoParser.DOT); + this.state = 47; + this.collection(); + } + break; + } + this.state = 52; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 50; + this.match(mongoParser.DOT); + this.state = 51; + this.functionCall(); + } + } + this.state = 54; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la === mongoParser.DOT); + this.state = 57; + this._errHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this._input, 4, this._ctx) + ) { + case 1: + { + this.state = 56; + this.match(mongoParser.SEMICOLON); + } + break; + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public emptyCommand(): EmptyCommandContext { + const _localctx: EmptyCommandContext = new EmptyCommandContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 59; + this.match(mongoParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public collection(): CollectionContext { + const _localctx: CollectionContext = new CollectionContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 8, mongoParser.RULE_collection); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 61; + this.match(mongoParser.IDENTIFIER); + this.state = 66; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 5, + this._ctx + ); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 62; + this.match(mongoParser.DOT); + this.state = 63; + this.match(mongoParser.IDENTIFIER); + } + } + } + this.state = 68; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 5, + this._ctx + ); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public functionCall(): FunctionCallContext { + const _localctx: FunctionCallContext = new FunctionCallContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 69; + _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); + this.state = 70; + this.arguments(); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arguments(): ArgumentsContext { + const _localctx: ArgumentsContext = new ArgumentsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 12, mongoParser.RULE_arguments); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 72; + _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); + this.state = 81; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.T__3) | + (1 << mongoParser.T__5) | + (1 << mongoParser.RegexLiteral) | + (1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral) | + (1 << mongoParser.NumericLiteral))) !== + 0 + ) { + { + this.state = 73; + this.argument(); + this.state = 78; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 74; + this.match(mongoParser.T__1); + this.state = 75; + this.argument(); + } + } + this.state = 80; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + this.state = 83; + _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public argument(): ArgumentContext { + const _localctx: ArgumentContext = new ArgumentContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 14, mongoParser.RULE_argument); + try { + this.state = 88; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 85; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 86; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 87; + this.arrayLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public objectLiteral(): ObjectLiteralContext { + const _localctx: ObjectLiteralContext = new ObjectLiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 90; + this.match(mongoParser.T__3); + this.state = 92; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + _la === mongoParser.StringLiteral || + _la === mongoParser.IDENTIFIER + ) { + { + this.state = 91; + this.propertyNameAndValueList(); + } + } + + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.T__1) { + { + this.state = 94; + this.match(mongoParser.T__1); + } + } + + this.state = 97; + this.match(mongoParser.T__4); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arrayLiteral(): ArrayLiteralContext { + const _localctx: ArrayLiteralContext = new ArrayLiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 99; + this.match(mongoParser.T__5); + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.T__3) | + (1 << mongoParser.T__5) | + (1 << mongoParser.RegexLiteral) | + (1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral) | + (1 << mongoParser.NumericLiteral) | + (1 << mongoParser.IDENTIFIER))) !== + 0 + ) { + { + this.state = 100; + this.elementList(); + } + } + + this.state = 103; + this.match(mongoParser.T__6); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public elementList(): ElementListContext { + const _localctx: ElementListContext = new ElementListContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 20, mongoParser.RULE_elementList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 105; + this.propertyValue(); + this.state = 110; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 106; + this.match(mongoParser.T__1); + this.state = 107; + this.propertyValue(); + } + } + this.state = 112; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyNameAndValueList(): PropertyNameAndValueListContext { + const _localctx: PropertyNameAndValueListContext = + new PropertyNameAndValueListContext(this._ctx, this.state); + this.enterRule( + _localctx, + 22, + mongoParser.RULE_propertyNameAndValueList + ); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 113; + this.propertyAssignment(); + this.state = 118; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 13, + this._ctx + ); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 114; + this.match(mongoParser.T__1); + this.state = 115; + this.propertyAssignment(); + } + } + } + this.state = 120; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 13, + this._ctx + ); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyAssignment(): PropertyAssignmentContext { + const _localctx: PropertyAssignmentContext = + new PropertyAssignmentContext(this._ctx, this.state); + this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 121; + this.propertyName(); + this.state = 122; + this.match(mongoParser.T__7); + this.state = 123; + this.propertyValue(); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyValue(): PropertyValueContext { + const _localctx: PropertyValueContext = new PropertyValueContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); + try { + this.state = 129; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 125; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 126; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 127; + this.arrayLiteral(); + } + break; + case mongoParser.IDENTIFIER: + this.enterOuterAlt(_localctx, 4); + { + this.state = 128; + this.functionCall(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public literal(): LiteralContext { + const _localctx: LiteralContext = new LiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 28, mongoParser.RULE_literal); + let _la: number; + try { + this.state = 134; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 131; + _la = this._input.LA(1); + if ( + !( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral))) !== + 0 + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + break; + case mongoParser.RegexLiteral: + this.enterOuterAlt(_localctx, 2); + { + this.state = 132; + this.match(mongoParser.RegexLiteral); + } + break; + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 3); + { + this.state = 133; + this.match(mongoParser.NumericLiteral); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyName(): PropertyNameContext { + const _localctx: PropertyNameContext = new PropertyNameContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 136; + _la = this._input.LA(1); + if ( + !( + _la === mongoParser.StringLiteral || + _la === mongoParser.IDENTIFIER + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public comment(): CommentContext { + const _localctx: CommentContext = new CommentContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 32, mongoParser.RULE_comment); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 138; + _la = this._input.LA(1); + if ( + !( + _la === mongoParser.SingleLineComment || + _la === mongoParser.MultiLineComment + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + + "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + + "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + + "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + + "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + + "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + + "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + + "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + + "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + + "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + + "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + + '\x1C\x02\x1E\x02 \x02"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17' + + "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + + "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + + "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + + "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + + "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + + '\x02\x02"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03' + + "\x03\x02\x02\x02'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*'" + + "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + + ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + + "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + + "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + + "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + + "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + + "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + + "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + + "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + + "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + + "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + + "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + + "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + + "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + + "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + + "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + + "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + + "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + + "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + + "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + + "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + + "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + + "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + + "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + + "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + + "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + + "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + + "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + + "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + + "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + + "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + + "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + + "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoParser.__ATN) { + mongoParser.__ATN = new ATNDeserializer().deserialize( + Utils.toCharArray(mongoParser._serializedATN) + ); + } + + return mongoParser.__ATN; + } } export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } + public commands(): CommandsContext { + return this.getRuleContext(0, CommandsContext); + } + public EOF(): TerminalNode { + return this.getToken(mongoParser.EOF, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_mongoCommands; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterMongoCommands) listener.enterMongoCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitMongoCommands) listener.exitMongoCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); + else return visitor.visitChildren(this); + } } - export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } + public command(): CommandContext[]; + public command(i: number): CommandContext; + public command(i?: number): CommandContext | CommandContext[] { + if (i === undefined) { + return this.getRuleContexts(CommandContext); + } else { + return this.getRuleContext(i, CommandContext); + } + } + public emptyCommand(): EmptyCommandContext[]; + public emptyCommand(i: number): EmptyCommandContext; + public emptyCommand( + i?: number + ): EmptyCommandContext | EmptyCommandContext[] { + if (i === undefined) { + return this.getRuleContexts(EmptyCommandContext); + } else { + return this.getRuleContext(i, EmptyCommandContext); + } + } + public comment(): CommentContext[]; + public comment(i: number): CommentContext; + public comment(i?: number): CommentContext | CommentContext[] { + if (i === undefined) { + return this.getRuleContexts(CommentContext); + } else { + return this.getRuleContext(i, CommentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_commands; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommands) listener.enterCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommands) listener.exitCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommands) return visitor.visitCommands(this); + else return visitor.visitChildren(this); + } } - export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_command; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } + public DB(): TerminalNode { + return this.getToken(mongoParser.DB, 0); + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + public collection(): CollectionContext | undefined { + return this.tryGetRuleContext(0, CollectionContext); + } + public functionCall(): FunctionCallContext[]; + public functionCall(i: number): FunctionCallContext; + public functionCall( + i?: number + ): FunctionCallContext | FunctionCallContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionCallContext); + } else { + return this.getRuleContext(i, FunctionCallContext); + } + } + public SEMICOLON(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.SEMICOLON, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_command; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommand) listener.enterCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommand) listener.exitCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommand) return visitor.visitCommand(this); + else return visitor.visitChildren(this); + } } - export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } + public SEMICOLON(): TerminalNode { + return this.getToken(mongoParser.SEMICOLON, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_emptyCommand; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); + else return visitor.visitChildren(this); + } } - export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.IDENTIFIER); + } else { + return this.getToken(mongoParser.IDENTIFIER, i); + } + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_collection; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCollection) listener.enterCollection(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCollection) listener.exitCollection(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCollection) return visitor.visitCollection(this); + else return visitor.visitChildren(this); + } } - export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } + public _FUNCTION_NAME: Token; + public arguments(): ArgumentsContext { + return this.getRuleContext(0, ArgumentsContext); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(mongoParser.IDENTIFIER, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_functionCall; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterFunctionCall) listener.enterFunctionCall(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitFunctionCall) listener.exitFunctionCall(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); + else return visitor.visitChildren(this); + } } - export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } + public _OPEN_PARENTHESIS: Token; + public _CLOSED_PARENTHESIS: Token; + public argument(): ArgumentContext[]; + public argument(i: number): ArgumentContext; + public argument(i?: number): ArgumentContext | ArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(ArgumentContext); + } else { + return this.getRuleContext(i, ArgumentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_arguments; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArguments) listener.enterArguments(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArguments) listener.exitArguments(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArguments) return visitor.visitArguments(this); + else return visitor.visitChildren(this); + } } - export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_argument; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArgument) listener.enterArgument(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArgument) listener.exitArgument(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArgument) return visitor.visitArgument(this); + else return visitor.visitChildren(this); + } } - export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } + public propertyNameAndValueList(): + | PropertyNameAndValueListContext + | undefined { + return this.tryGetRuleContext(0, PropertyNameAndValueListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_objectLiteral; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); + else return visitor.visitChildren(this); + } } - export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } + public elementList(): ElementListContext | undefined { + return this.tryGetRuleContext(0, ElementListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_arrayLiteral; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); + else return visitor.visitChildren(this); + } } - export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } + public propertyValue(): PropertyValueContext[]; + public propertyValue(i: number): PropertyValueContext; + public propertyValue( + i?: number + ): PropertyValueContext | PropertyValueContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyValueContext); + } else { + return this.getRuleContext(i, PropertyValueContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_elementList; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterElementList) listener.enterElementList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitElementList) listener.exitElementList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitElementList) return visitor.visitElementList(this); + else return visitor.visitChildren(this); + } } - export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } + public propertyAssignment(): PropertyAssignmentContext[]; + public propertyAssignment(i: number): PropertyAssignmentContext; + public propertyAssignment( + i?: number + ): PropertyAssignmentContext | PropertyAssignmentContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyAssignmentContext); + } else { + return this.getRuleContext(i, PropertyAssignmentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyNameAndValueList; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyNameAndValueList) + listener.enterPropertyNameAndValueList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyNameAndValueList) + listener.exitPropertyNameAndValueList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyNameAndValueList) + return visitor.visitPropertyNameAndValueList(this); + else return visitor.visitChildren(this); + } } - export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } + public propertyName(): PropertyNameContext { + return this.getRuleContext(0, PropertyNameContext); + } + public propertyValue(): PropertyValueContext { + return this.getRuleContext(0, PropertyValueContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyAssignment; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyAssignment) + listener.enterPropertyAssignment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyAssignment) + listener.exitPropertyAssignment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyAssignment) + return visitor.visitPropertyAssignment(this); + else return visitor.visitChildren(this); + } } - export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + public functionCall(): FunctionCallContext | undefined { + return this.tryGetRuleContext(0, FunctionCallContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyValue; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyValue) listener.enterPropertyValue(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyValue) listener.exitPropertyValue(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); + else return visitor.visitChildren(this); + } } - export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } - public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } - public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } + public NullLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.NullLiteral, 0); + } + public BooleanLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.BooleanLiteral, 0); + } + public StringLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.StringLiteral, 0); + } + public RegexLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.RegexLiteral, 0); + } + public NumericLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.NumericLiteral, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_literal; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterLiteral) listener.enterLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitLiteral) listener.exitLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitLiteral) return visitor.visitLiteral(this); + else return visitor.visitChildren(this); + } } - export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } + public StringLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.StringLiteral, 0); + } + public IDENTIFIER(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.IDENTIFIER, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyName; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyName) listener.enterPropertyName(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyName) listener.exitPropertyName(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyName) return visitor.visitPropertyName(this); + else return visitor.visitChildren(this); + } } - export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } - public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } + public SingleLineComment(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.SingleLineComment, 0); + } + public MultiLineComment(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.MultiLineComment, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_comment; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterComment) listener.enterComment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitComment) listener.exitComment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitComment) return visitor.visitComment(this); + else return visitor.visitChildren(this); + } } - - diff --git a/Source/mongo/grammar/mongoVisitor.ts b/Source/mongo/grammar/mongoVisitor.ts index eb001a6e9..105184d2d 100644 --- a/Source/mongo/grammar/mongoVisitor.ts +++ b/Source/mongo/grammar/mongoVisitor.ts @@ -1,17 +1,30 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - - -import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - +import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; +import { + ArgumentContext, + ArgumentsContext, + ArrayLiteralContext, + CollectionContext, + CommandContext, + CommandsContext, + CommentContext, + ElementListContext, + EmptyCommandContext, + FunctionCallContext, + LiteralContext, + MongoCommandsContext, + ObjectLiteralContext, + PropertyAssignmentContext, + PropertyNameAndValueListContext, + PropertyNameContext, + PropertyValueContext, +} from "./mongoParser"; /** * This interface defines a complete generic visitor for a parse tree produced @@ -103,7 +116,9 @@ export interface mongoVisitor extends ParseTreeVisitor { * @param ctx the parse tree * @return the visitor result */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; + visitPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => Result; /** * Visit a parse tree produced by `mongoParser.propertyAssignment`. @@ -140,4 +155,3 @@ export interface mongoVisitor extends ParseTreeVisitor { */ visitComment?: (ctx: CommentContext) => Result; } - diff --git a/Source/mongo/grammar/visitors.ts b/Source/mongo/grammar/visitors.ts index e1ba1b63d..20e69315d 100644 --- a/Source/mongo/grammar/visitors.ts +++ b/Source/mongo/grammar/visitors.ts @@ -3,81 +3,88 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; -import { mongoVisitor } from './mongoVisitor'; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { + ArgumentContext, + ArgumentsContext, + CollectionContext, + CommandContext, + CommandsContext, + FunctionCallContext, + MongoCommandsContext, +} from "./mongoParser"; +import { mongoVisitor } from "./mongoVisitor"; export class MongoVisitor implements mongoVisitor { - - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return null; - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } + visitMongoCommands(ctx: MongoCommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommands(ctx: CommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommand(ctx: CommandContext): T { + return this.visitChildren(ctx); + } + + visitCollection(ctx: CollectionContext): T { + return this.visitChildren(ctx); + } + + visitFunctionCall(ctx: FunctionCallContext): T { + return this.visitChildren(ctx); + } + + visitArgument(ctx: ArgumentContext): T { + return this.visitChildren(ctx); + } + + visitArguments(ctx: ArgumentsContext): T { + return this.visitChildren(ctx); + } + + visit(tree: ParseTree): T { + return tree.accept(this); + } + + visitChildren(ctx: ParserRuleContext): T { + let result = this.defaultResult(ctx); + const n = ctx.childCount; + for (let i = 0; i < n; i++) { + if (!this.shouldVisitNextChild(ctx, result)) { + break; + } + + const childNode = ctx.getChild(i); + const childResult = childNode.accept(this); + result = this.aggregateResult(result, childResult); + } + return result; + } + + visitTerminal(node: TerminalNode): T { + return this.defaultResult(node); + } + + visitErrorNode(node: ErrorNode): T { + return this.defaultResult(node); + } + + protected defaultResult(_node: ParseTree): T { + // grandfathered-in. Unclear why this is null instead of type T + return (null); + } + + protected aggregateResult(aggregate: T, nextResult: T): T { + return !nextResult ? aggregate : nextResult; + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + shouldVisitNextChild(_node, _currentResult: T): boolean { + return true; + } } diff --git a/Source/mongo/languageClient.ts b/Source/mongo/languageClient.ts index e4bd4aefd..6f445423e 100644 --- a/Source/mongo/languageClient.ts +++ b/Source/mongo/languageClient.ts @@ -2,57 +2,81 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -import * as nls from 'vscode-nls'; -import { ext } from '../extensionVariables'; -import { IConnectionParams } from './services/IConnectionParams'; +import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; +import * as path from "path"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from "vscode-languageclient"; +import * as nls from "vscode-nls"; +import { ext } from "../extensionVariables"; +import { IConnectionParams } from "./services/IConnectionParams"; const localize = nls.loadMessageBundle(); export class MongoDBLanguageClient { + public client: LanguageClient; - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle ? - ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : - ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'mongo', scheme: 'file' }, - { language: 'mongo', scheme: 'untitled' } - ] - }; - - // Create the language client and start the client. - this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect(connectionString: string, databaseName: string): Promise { - await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } + constructor() { + // The server is implemented in node + const serverModule = ext.ignoreBundle + ? ext.context.asAbsolutePath( + path.join("out", "src", "mongo", "languageServer.js") + ) + : ext.context.asAbsolutePath( + path.join("dist", "mongo-languageServer.bundle.js") + ); + // The debug options for the server + const debugOptions = { execArgv: ["--nolazy", "--inspect=6005"] }; + + // If the extension is launch in debug mode the debug server options are use + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + options: debugOptions, + }, + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for mongo javascript documents + documentSelector: [ + { language: "mongo", scheme: "file" }, + { language: "mongo", scheme: "untitled" }, + ], + }; + + // Create the language client and start the client. + this.client = new LanguageClient( + "mongo", + localize("mongo.server.name", "Mongo Language Server"), + serverOptions, + clientOptions + ); + const disposable = this.client.start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + ext.context.subscriptions.push(disposable); + } + + public async connect( + connectionString: string, + databaseName: string + ): Promise { + await this.client.sendRequest("connect", { + connectionString: connectionString, + databaseName: databaseName, + extensionUserAgent: appendExtensionUserAgent(), + }); + } + + public async disconnect(): Promise { + await this.client.sendRequest("disconnect"); + } } diff --git a/Source/mongo/languageServer.ts b/Source/mongo/languageServer.ts index d5d6ec484..8c76686f6 100644 --- a/Source/mongo/languageServer.ts +++ b/Source/mongo/languageServer.ts @@ -2,8 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from 'vscode-languageserver'; -import { LanguageService } from './services/languageService'; +import { createConnection, IConnection } from "vscode-languageserver"; +import { LanguageService } from "./services/languageService"; // // diff --git a/Source/mongo/mongoConnectionStrings.ts b/Source/mongo/mongoConnectionStrings.ts index 5f73db484..89d04ed30 100644 --- a/Source/mongo/mongoConnectionStrings.ts +++ b/Source/mongo/mongoConnectionStrings.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; +import { + appendExtensionUserAgent, + IParsedError, + parseError, +} from "@microsoft/vscode-azext-utils"; import { MongoClient } from "mongodb"; import { testDb } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; @@ -21,84 +25,118 @@ import { connectToMongoClient } from "./connectToMongoClient"; // mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] // [database] -const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; -const parseDatabaseName = '\/?([^/?]+)?'; +const parsePrefix = "([a-zA-Z]+://[^/]*)"; +const parseDatabaseName = "/?([^/?]+)?"; const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } +export function getDatabaseNameFromConnectionString( + connectionString: string +): string | undefined { + try { + const [, , databaseName] = nonNullValue( + connectionString.match(mongoConnectionStringRegExp), + "databaseNameMatch" + ); + return databaseName; + } catch (error) { + // Shouldn't happen, but ignore if does + } - return undefined; + return undefined; } -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } +export function addDatabaseToAccountConnectionString( + connectionString: string, + databaseName: string +): string { + try { + return connectionString.replace( + mongoConnectionStringRegExp, + `$1\/${encodeURIComponent(databaseName)}` + ); + } catch (error) { + // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it + return connectionString; + } } -export async function parseMongoConnectionString(connectionString: string): Promise { +export async function parseMongoConnectionString( + connectionString: string +): Promise { + let mongoClient: MongoClient; + try { + mongoClient = await connectToMongoClient( + connectionString, + appendExtensionUserAgent() + ); + } catch (error) { + const parsedError: IParsedError = parseError(error); + if (parsedError.message.match(/unescaped/i)) { + // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 + connectionString = encodeMongoConnectionString(connectionString); + mongoClient = await connectToMongoClient( + connectionString, + appendExtensionUserAgent() + ); + } else { + throw error; + } + } - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const serverConfig: any = mongoClient.db(testDb).serverConfig; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; + // get the first connection string from the servers list + // this may not be best solution, but the connection (below) gives + // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) + // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const host: string = + serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const port: string = + serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - - return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); + return new ParsedMongoConnectionString( + connectionString, + host, + port, + getDatabaseNameFromConnectionString(connectionString) + ); } export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } + constructor( + connectionString: string, + hostName: string, + port: string, + databaseName: string | undefined + ) { + super(connectionString, databaseName); + this.hostName = hostName; + this.port = port; + } } /** * Encodes the username and password in the given Mongo DB connection string. */ export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } + const matches: RegExpMatchArray | null = connectionString.match( + /^(.*):\/\/(.*):(.*)@(.*)/ + ); + if (matches) { + const prefix: string = matches[1]; + const username: string = matches[2]; + const password: string = matches[3]; + const hostAndQuery: string = matches[4]; + connectionString = `${prefix}://${encodeURIComponent( + username + )}:${encodeURIComponent(password)}@${hostAndQuery}`; + } - return connectionString; + return connectionString; } diff --git a/Source/mongo/registerMongoCommands.ts b/Source/mongo/registerMongoCommands.ts index 2dc36477a..713ff9104 100644 --- a/Source/mongo/registerMongoCommands.ts +++ b/Source/mongo/registerMongoCommands.ts @@ -3,15 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { Experience, MongoExperience } from '../AzureDBExperiences'; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, + IErrorHandlerContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, + registerErrorHandler, + registerEvent, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { Experience, MongoExperience } from "../AzureDBExperiences"; import { cosmosMongoFilter } from "../constants"; import { ext } from "../extensionVariables"; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { MongoConnectError } from './connectToMongoClient'; +import * as vscodeUtil from "../utils/vscodeUtils"; +import { MongoConnectError } from "./connectToMongoClient"; import { MongoDBLanguageClient } from "./languageClient"; -import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; +import { + executeAllCommandsFromActiveEditor, + executeCommandFromActiveEditor, + getAllErrorsFromTextDocument, +} from "./MongoScrapbook"; import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; import { setConnectedNode } from "./setConnectedNode"; import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; @@ -19,205 +32,328 @@ import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; -const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; +const connectedMongoKey: string = "ms-azuretools.vscode-cosmosdb.connectedDB"; let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = 'mongo'; +const mongoLanguageId: string = "mongo"; export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); - } - - const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); - if (oldNode) { - await oldNode.refresh(context); - } - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); - registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - }); + ext.mongoLanguageClient = new MongoDBLanguageClient(); + + ext.mongoCodeLensProvider = new MongoCodeLensProvider(); + ext.context.subscriptions.push( + vscode.languages.registerCodeLensProvider( + mongoLanguageId, + ext.mongoCodeLensProvider + ) + ); + + diagnosticsCollection = + vscode.languages.createDiagnosticCollection("cosmosDB.mongo"); + ext.context.subscriptions.push(diagnosticsCollection); + + setUpErrorReporting(); + + const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); + + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoDatabase", + createMongoDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoCollection", + createMongoCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoDocument", + async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + const documentNode = await node.createChild(context); + await vscode.commands.executeCommand( + "cosmosDB.openDocument", + documentNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.connectMongoDB", + async (context: IActionContext, node?: MongoDatabaseTreeItem) => { + if (!node) { + // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 + const experienceContext: ITreeItemPickerContext & { + defaultExperience?: Experience; + } = { ...context, defaultExperience: MongoExperience }; + node = await pickMongo( + experienceContext, + MongoDatabaseTreeItem.contextValue + ); + } + + const oldNodeId: string | undefined = + ext.connectedMongoDB && ext.connectedMongoDB.fullId; + await ext.mongoLanguageClient.connect( + node.connectionString, + node.databaseName + ); + void ext.context.globalState.update(connectedMongoKey, node.fullId); + setConnectedNode(node); + await node.refresh(context); + + if (oldNodeId) { + // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldNode: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + oldNodeId, + context + ); + if (oldNode) { + await oldNode.refresh(context); + } + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoDB", + deleteMongoDB + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoCollection", + deleteMongoCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoDocument", + async (context: IActionContext, node?: MongoDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoDocumentTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openCollection", + async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + await ext.fileSystem.showTextDocument(node); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.launchMongoShell", + launchMongoShell + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.newMongoScrapbook", + async () => await vscodeUtil.showNewFile("", "Scrapbook", ".mongo") + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.executeMongoCommand", + async (context: IActionContext, position?: vscode.Position) => { + await loadPersistedMongoDBTask; + await executeCommandFromActiveEditor(context, position); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.executeAllMongoCommands", + async (context: IActionContext) => { + await loadPersistedMongoDBTask; + await executeAllCommandsFromActiveEditor(context); + } + ); } async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling( + "cosmosDB.loadPersistedMongoDB", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = "true"; + + try { + const persistedNodeId: string | undefined = + ext.context.globalState.get(connectedMongoKey); + if (persistedNodeId) { + const persistedNode = + await ext.rgApi.appResourceTree.findTreeItem( + persistedNodeId, + context + ); + if (persistedNode) { + await ext.mongoLanguageClient.client.onReady(); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + persistedNode + ); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedMongoDB) { + ext.mongoCodeLensProvider.setConnectedDatabase(undefined); + } + } + } + ); } function launchMongoShell(): void { - const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); - terminal.sendText(`mongo`); - terminal.show(); + const terminal: vscode.Terminal = + vscode.window.createTerminal("Mongo Shell"); + terminal.sendText(`mongo`); + terminal.show(); } function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }); - - // Update errors when document opened/changed - registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); + // Update errors immediately in case a scrapbook is already open + void callWithTelemetryAndErrorHandling( + "initialUpdateErrorsInActiveDocument", + async (context: IActionContext) => { + updateErrorsInScrapbook( + context, + vscode.window.activeTextEditor?.document + ); + } + ); + + // Update errors when document opened/changed + registerEvent( + "vscode.workspace.onDidOpenTextDocument", + vscode.workspace.onDidOpenTextDocument, + updateErrorsInScrapbook + ); + registerEvent( + "vscode.workspace.onDidChangeTextDocument", + vscode.workspace.onDidChangeTextDocument, + async ( + context: IActionContext, + event: vscode.TextDocumentChangeEvent + ) => { + // Always suppress success telemetry - event happens on every keystroke + context.telemetry.suppressIfSuccessful = true; + + updateErrorsInScrapbook(context, event.document); + } + ); + registerEvent( + "vscode.workspace.onDidCloseTextDocument", + vscode.workspace.onDidCloseTextDocument, + async (context: IActionContext, document: vscode.TextDocument) => { + // Remove errors when closed + if (document?.languageId === mongoLanguageId) { + diagnosticsCollection.set(document.uri, []); + } else { + context.telemetry.suppressIfSuccessful = true; + } + } + ); + + registerErrorHandler((context: IErrorHandlerContext) => { + if (context.error instanceof MongoConnectError) { + context.errorHandling.suppressReportIssue = true; + } + }); } -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } +function updateErrorsInScrapbook( + context: IActionContext, + document: vscode.TextDocument | undefined +): void { + if (document?.languageId === mongoLanguageId) { + const errors = getAllErrorsFromTextDocument(document); + diagnosticsCollection.set(document.uri, errors); + } else { + context.telemetry.suppressIfSuccessful = true; + } } -export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); +export async function createMongoDatabase( + context: IActionContext, + node?: MongoAccountTreeItem +): Promise { + if (!node) { + node = await pickMongo(context); + } + const databaseNode = await node.createChild(context); + await databaseNode.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + databaseNode + ); } -export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); +export async function createMongoCollection( + context: IActionContext, + node?: MongoDatabaseTreeItem +): Promise { + if (!node) { + node = await pickMongo( + context, + MongoDatabaseTreeItem.contextValue + ); + } + const collectionNode = await node.createChild(context); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + collectionNode.parent + ); } -export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } +export async function deleteMongoDB( + context: IActionContext, + node?: MongoDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { + setConnectedNode(undefined); + void ext.context.globalState.update(connectedMongoKey, undefined); + // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 + void ext.mongoLanguageClient.disconnect(); + } } -export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteMongoCollection( + context: IActionContext, + node?: MongoCollectionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickMongo( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [cosmosMongoFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/mongo/services/IConnectionParams.ts b/Source/mongo/services/IConnectionParams.ts index eec39e4cf..55d2cc73a 100644 --- a/Source/mongo/services/IConnectionParams.ts +++ b/Source/mongo/services/IConnectionParams.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; + connectionString: string; + databaseName: string; + extensionUserAgent: string; } diff --git a/Source/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts index 3407c50dd..01aaff56f 100644 --- a/Source/mongo/services/MongoCodeLensProvider.ts +++ b/Source/mongo/services/MongoCodeLensProvider.ts @@ -3,73 +3,89 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: vscode.EventEmitter = + new vscode.EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): vscode.Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses( + document: vscode.TextDocument, + _token: vscode.CancellationToken + ): vscode.ProviderResult { + return callWithTelemetryAndErrorHandling( + "mongo.provideCodeLenses", + (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: vscode.CodeLens[] = []; - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized ? - 'Initializing...' : - isConnected ? - `Connected to ${database}` : - `Connect to a database`, - command: isInitialized && 'cosmosDB.connectMongoDB' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title: !isInitialized + ? "Initializing..." + : isConnected + ? `Connected to ${database}` + : `Connect to a database`, + command: isInitialized && "cosmosDB.connectMongoDB", + }, + range: new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(0, 0) + ), + }); - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: 'cosmosDB.executeAllMongoCommands' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); + if (isConnected) { + // Run all + lenses.push({ + command: { + title: "Execute All", + command: "cosmosDB.executeAllMongoCommands", + }, + range: new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(0, 0) + ), + }); - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: 'cosmosDB.executeMongoCommand', - arguments: [cmd.range.start] - }, - range: cmd.range - }); - } - } + const commands = getAllCommandsFromTextDocument(document); + for (const cmd of commands) { + // run individual + lenses.push({ + command: { + title: "Execute", + command: "cosmosDB.executeMongoCommand", + arguments: [cmd.range.start], + }, + range: cmd.range, + }); + } + } - return lenses; - }); - } + return lenses; + } + ); + } } diff --git a/Source/mongo/services/completionItemProvider.ts b/Source/mongo/services/completionItemProvider.ts index cba51890c..4abb71432 100644 --- a/Source/mongo/services/completionItemProvider.ts +++ b/Source/mongo/services/completionItemProvider.ts @@ -5,435 +5,588 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) - .then(list => { - return list!.items.map(item => { - const startPositionOffset = document.offsetAt(item.textEdit!.range.start); - const endPositionOffset = document.offsetAt(item.textEdit!.range.end); - item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range - }, - kind: CompletionItemKind.Keyword, - label: 'db' - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range) - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then(collections => { - return collections.map(collection => ({ - textEdit: { - newText: collection.collectionName, - range - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}` - })); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range) - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}` - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } - +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Db } from "mongodb"; +import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; +import { + CompletionItem, + CompletionItemKind, + Position, + Range, +} from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { mongoLexer } from "./../grammar/mongoLexer"; +import * as mongoParser from "./../grammar/mongoParser"; +import { MongoVisitor } from "./../grammar/visitors"; +import { SchemaService } from "./schemaService"; + +export class CompletionItemsVisitor extends MongoVisitor< + Promise +> { + private at: Position; + + constructor( + private textDocument: TextDocument, + private db: Db, + private offset: number, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + super(); + this.at = this.textDocument.positionAt(this.offset); + } + + public visitCommands( + ctx: mongoParser.CommandsContext + ): Promise { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(ctx)) + ); + } + + public visitEmptyCommand( + ctx: mongoParser.EmptyCommandContext + ): Promise { + return this.thenable( + this.createDbKeywordCompletion(this.createRangeAfter(ctx)) + ); + } + + public visitCommand( + ctx: mongoParser.CommandContext + ): Promise { + if (ctx.childCount === 0) { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(ctx)) + ); + } + + const lastTerminalNode = this.getLastTerminalNode(ctx); + if (lastTerminalNode) { + return this.getCompletionItemsFromTerminalNode(lastTerminalNode); + } + return this.thenable(); + } + + public visitCollection( + ctx: mongoParser.CollectionContext + ): Promise { + return Promise.all([ + this.createCollectionCompletions(this.createRange(ctx)), + this.createDbFunctionCompletions(this.createRange(ctx)), + ]).then(([collectionCompletions, dbFunctionCompletions]) => [ + ...collectionCompletions, + ...dbFunctionCompletions, + ]); + } + + public visitFunctionCall( + ctx: mongoParser.FunctionCallContext + ): Promise { + const previousNode = this.getPreviousNode(ctx); + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return this.thenable(); + } + + public visitArguments( + ctx: mongoParser.ArgumentsContext + ): Promise { + const terminalNode = this.getLastTerminalNode(ctx); + if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { + return this.thenable( + this.createDbKeywordCompletion( + this.createRangeAfter(terminalNode) + ) + ); + } + return this.thenable(); + } + + public visitArgument( + ctx: mongoParser.ArgumentContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitObjectLiteral( + ctx: mongoParser.ObjectLiteralContext + ): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if ( + [ + "find", + "findOne", + "findOneAndDelete", + "findOneAndUpdate", + "findOneAndReplace", + "deleteOne", + "deleteMany", + "remove", + ].indexOf(functionName) !== -1 + ) { + return this.getArgumentCompletionItems( + this.schemaService.queryDocumentUri(collectionName), + collectionName, + ctx + ); + } + } + return ctx.parent!.accept(this); + } + + public visitArrayLiteral( + ctx: mongoParser.ArrayLiteralContext + ): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (["aggregate"].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems( + this.schemaService.aggregateDocumentUri(collectionName), + collectionName, + ctx + ); + } + } + return ctx.parent!.accept(this); + } + + public visitElementList( + ctx: mongoParser.ElementListContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyNameAndValueList( + ctx: mongoParser.PropertyNameAndValueListContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyAssignment( + ctx: mongoParser.PropertyAssignmentContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyValue( + ctx: mongoParser.PropertyValueContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyName( + ctx: mongoParser.PropertyNameContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitLiteral( + ctx: mongoParser.LiteralContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitTerminal(ctx: TerminalNode): Promise { + return ctx.parent!.accept(this); + } + + public visitErrorNode(ctx: ErrorNode): Promise { + return ctx.parent!.accept(this); + } + + private getArgumentCompletionItems( + documentUri: string, + _collectionName: string, + ctx: ParserRuleContext + ): Thenable { + const text = this.textDocument.getText(); + const document = TextDocument.create( + documentUri, + "json", + 1, + text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1) + ); + const positionOffset = this.textDocument.offsetAt(this.at); + const contextOffset = ctx.start.startIndex; + const position = document.positionAt(positionOffset - contextOffset); + return this.jsonLanguageService + .doComplete( + document, + position, + this.jsonLanguageService.parseJSONDocument(document) + ) + .then((list) => { + return list!.items.map((item) => { + const startPositionOffset = document.offsetAt( + item.textEdit!.range.start + ); + const endPositionOffset = document.offsetAt( + item.textEdit!.range.end + ); + item.textEdit!.range = Range.create( + this.textDocument.positionAt( + startPositionOffset + contextOffset + ), + this.textDocument.positionAt( + contextOffset + endPositionOffset + ) + ); + return item; + }); + }); + } + + private getFunctionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + return (parent)._FUNCTION_NAME.text!; + } + + private getCollectionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + let previousNode = this.getPreviousNode(parent); + if ( + previousNode && + previousNode instanceof TerminalNode && + previousNode.symbol.type === mongoLexer.DOT + ) { + previousNode = this.getPreviousNode(previousNode); + if ( + previousNode && + previousNode instanceof mongoParser.CollectionContext + ) { + return previousNode.text; + } + } + return null!; + } + + private getCompletionItemsFromTerminalNode( + node: TerminalNode + ): Promise { + if (node._symbol.type === mongoParser.mongoParser.DB) { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(node)) + ); + } + if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { + return this.thenable( + this.createDbKeywordCompletion(this.createRangeAfter(node)) + ); + } + if (node._symbol.type === mongoParser.mongoParser.DOT) { + const previousNode = this.getPreviousNode(node); + if (previousNode && previousNode instanceof TerminalNode) { + if (previousNode._symbol.type === mongoParser.mongoParser.DB) { + return Promise.all([ + this.createCollectionCompletions( + this.createRangeAfter(node) + ), + this.createDbFunctionCompletions( + this.createRangeAfter(node) + ), + ]).then( + ([collectionCompletions, dbFunctionCompletions]) => [ + ...collectionCompletions, + ...dbFunctionCompletions, + ] + ); + } + } + if (previousNode instanceof mongoParser.CollectionContext) { + return this.createCollectionFunctionsCompletions( + this.createRangeAfter(node) + ); + } + } + if (node instanceof ErrorNode) { + const previousNode = this.getPreviousNode(node); + if (previousNode) { + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode( + previousNode + ); + } + return previousNode.accept(this); + } + } + return this.thenable(); + } + + private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { + return ctx.children ? ctx.children + .slice() + .reverse() + .filter( + (node) => + node instanceof TerminalNode && + node.symbol.stopIndex > -1 && + node.symbol.stopIndex < this.offset + )[0] : null!; + } + + private getPreviousNode(node: ParseTree): ParseTree { + let previousNode: ParseTree = null!; + const parentNode = node.parent!; + for (let i = 0; i < parentNode.childCount; i++) { + const currentNode = parentNode.getChild(i); + if (currentNode === node) { + break; + } + previousNode = currentNode; + } + return previousNode; + } + + private createDbKeywordCompletion(range: Range): CompletionItem { + return { + textEdit: { + newText: "db", + range, + }, + kind: CompletionItemKind.Keyword, + label: "db", + }; + } + + private createDbFunctionCompletions( + range: Range + ): Promise { + return this.thenable( + this.createFunctionCompletion("adminCommand", range), + this.createFunctionCompletion("auth", range), + this.createFunctionCompletion("cloneDatabase", range), + this.createFunctionCompletion("commandHelp", range), + this.createFunctionCompletion("copyDatabase", range), + this.createFunctionCompletion("createCollection", range), + this.createFunctionCompletion("createView", range), + this.createFunctionCompletion("createUser", range), + this.createFunctionCompletion("currentOp", range), + this.createFunctionCompletion("dropDatabase", range), + this.createFunctionCompletion("eval", range), + this.createFunctionCompletion("fsyncLock", range), + this.createFunctionCompletion("fsyncUnLock", range), + this.createFunctionCompletion("getCollection", range), + this.createFunctionCompletion("getCollectionInfos", range), + this.createFunctionCompletion("getCollectionNames", range), + this.createFunctionCompletion("getLastError", range), + this.createFunctionCompletion("getLastErrorObj", range), + this.createFunctionCompletion("getLogComponents", range), + this.createFunctionCompletion("getMongo", range), + this.createFunctionCompletion("getName", range), + this.createFunctionCompletion("getPrevError", range), + this.createFunctionCompletion("getProfilingLevel", range), + this.createFunctionCompletion("getProfilingStatus", range), + this.createFunctionCompletion("getReplicationInfo", range), + this.createFunctionCompletion("getSiblingDB", range), + this.createFunctionCompletion("getWriteConcern", range), + this.createFunctionCompletion("hostInfo", range), + this.createFunctionCompletion("isMaster", range), + this.createFunctionCompletion("killOp", range), + this.createFunctionCompletion("listCommands", range), + this.createFunctionCompletion("loadServerScripts", range), + this.createFunctionCompletion("logout", range), + this.createFunctionCompletion("printCollectionStats", range), + this.createFunctionCompletion("printReplicationInfo", range), + this.createFunctionCompletion("printShardingStatus", range), + this.createFunctionCompletion("printSlaveReplicationInfo", range), + this.createFunctionCompletion("dropUser", range), + this.createFunctionCompletion("repairDatabase", range), + this.createFunctionCompletion("runCommand", range), + this.createFunctionCompletion("serverStatus", range), + this.createFunctionCompletion("setLogLevel", range), + this.createFunctionCompletion("setProfilingLevel", range), + this.createFunctionCompletion("setWriteConcern", range), + this.createFunctionCompletion("unsetWriteConcern", range), + this.createFunctionCompletion("setVerboseShell", range), + this.createFunctionCompletion("shotdownServer", range), + this.createFunctionCompletion("stats", range), + this.createFunctionCompletion("version", range) + ); + } + + private createCollectionCompletions( + range: Range + ): Promise { + if (this.db) { + return >( + this.db.collections().then((collections) => { + return collections.map( + (collection) => + { + textEdit: { + newText: collection.collectionName, + range, + }, + label: collection.collectionName, + kind: CompletionItemKind.Property, + filterText: collection.collectionName, + sortText: `1:${collection.collectionName}`, + } + ); + }) + ); + } + return Promise.resolve([]); + } + + private createCollectionFunctionsCompletions( + range: Range + ): Promise { + return this.thenable( + this.createFunctionCompletion("bulkWrite", range), + this.createFunctionCompletion("count", range), + this.createFunctionCompletion("copyTo", range), + this.createFunctionCompletion("convertToCapped", range), + this.createFunctionCompletion("createIndex", range), + this.createFunctionCompletion("createIndexes", range), + this.createFunctionCompletion("dataSize", range), + this.createFunctionCompletion("deleteOne", range), + this.createFunctionCompletion("deleteMany", range), + this.createFunctionCompletion("distinct", range), + this.createFunctionCompletion("drop", range), + this.createFunctionCompletion("dropIndex", range), + this.createFunctionCompletion("dropIndexes", range), + this.createFunctionCompletion("ensureIndex", range), + this.createFunctionCompletion("explain", range), + this.createFunctionCompletion("reIndex", range), + this.createFunctionCompletion("find", range), + this.createFunctionCompletion("findOne", range), + this.createFunctionCompletion("findOneAndDelete", range), + this.createFunctionCompletion("findOneAndReplace", range), + this.createFunctionCompletion("findOneAndUpdate", range), + this.createFunctionCompletion("getDB", range), + this.createFunctionCompletion("getPlanCache", range), + this.createFunctionCompletion("getIndexes", range), + this.createFunctionCompletion("group", range), + this.createFunctionCompletion("insert", range), + this.createFunctionCompletion("insertOne", range), + this.createFunctionCompletion("insertMany", range), + this.createFunctionCompletion("mapReduce", range), + this.createFunctionCompletion("aggregate", range), + this.createFunctionCompletion("remove", range), + this.createFunctionCompletion("replaceOne", range), + this.createFunctionCompletion("renameCollection", range), + this.createFunctionCompletion("runCommand", range), + this.createFunctionCompletion("save", range), + this.createFunctionCompletion("stats", range), + this.createFunctionCompletion("storageSize", range), + this.createFunctionCompletion("totalIndexSize", range), + this.createFunctionCompletion("update", range), + this.createFunctionCompletion("updateOne", range), + this.createFunctionCompletion("updateMany", range), + this.createFunctionCompletion("validate", range), + this.createFunctionCompletion("getShardVersion", range), + this.createFunctionCompletion("getShardDistribution", range), + this.createFunctionCompletion("getSplitKeysForChunks", range), + this.createFunctionCompletion("getWriteConcern", range), + this.createFunctionCompletion("setWriteConcern", range), + this.createFunctionCompletion("unsetWriteConcern", range), + this.createFunctionCompletion("latencyStats", range) + ); + } + + private createFunctionCompletion( + label: string, + range: Range + ): CompletionItem { + return { + textEdit: { + newText: label, + range, + }, + kind: CompletionItemKind.Function, + label, + sortText: `2:${label}`, + }; + } + + private createRange(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + const startToken = parserRuleContext.start; + let stopToken = parserRuleContext.stop; + if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { + stopToken = startToken; + } + + const stop = stopToken.stopIndex; + return this._createRange(startToken.startIndex, stop); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange( + parserRuleContext.symbol.startIndex, + parserRuleContext.symbol.stopIndex + ); + } + + return null!; + } + + private createRangeAfter(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + let stopToken = parserRuleContext.stop; + if (!stopToken) { + stopToken = parserRuleContext.start; + } + + const stop = stopToken.stopIndex; + return this._createRange(stop + 1, stop + 1); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange( + parserRuleContext.symbol.stopIndex + 1, + parserRuleContext.symbol.stopIndex + 1 + ); + } + + //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want + // to introduce a regression bug. + return null!; + } + + private _createRange(start: number, end: number): Range { + const endPosition = this.textDocument.positionAt(end); + if (endPosition.line < this.at.line) { + return Range.create(Position.create(this.at.line, 0), this.at); + } + const startPosition = this.textDocument.positionAt(start); + return Range.create(startPosition, endPosition); + } + + private thenable( + ...completionItems: CompletionItem[] + ): Promise { + return Promise.resolve(completionItems || []); + } } diff --git a/Source/mongo/services/languageService.ts b/Source/mongo/services/languageService.ts index 83b1b594e..7629c9258 100644 --- a/Source/mongo/services/languageService.ts +++ b/Source/mongo/services/languageService.ts @@ -5,86 +5,119 @@ // NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) -import { Db } from 'mongodb'; -import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; -import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; +import { Db } from "mongodb"; +import { + getLanguageService, + LanguageService as JsonLanguageService, + SchemaConfiguration, +} from "vscode-json-languageservice"; +import { + CompletionItem, + IConnection, + InitializeParams, + InitializeResult, + TextDocumentPositionParams, + TextDocuments, + TextDocumentSyncKind, +} from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { IConnectionParams } from "./IConnectionParams"; +import { MongoScriptDocumentManager } from "./mongoScript"; +import { SchemaService } from "./schemaService"; export class LanguageService { - - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] } - } - }; - }); - - connection.onCompletion(textDocumentPosition => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) - .then(account => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db) - .then(schemas => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: uri => this.schemaService.resolveSchema(uri), - contributions: [] - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas - }); - } + private textDocuments: TextDocuments = new TextDocuments( + TextDocument + ); + private readonly mongoDocumentsManager: MongoScriptDocumentManager; + private db: Db; + + private jsonLanguageService: JsonLanguageService; + private schemaService: SchemaService; + private schemas: SchemaConfiguration[]; + + constructor(connection: IConnection) { + this.schemaService = new SchemaService(); + + this.textDocuments.listen(connection); + // After the server has started the client sends an initilize request. The server receives + // in the passed params the rootPath of the workspace plus the client capabilities. + connection.onInitialize( + (_params: InitializeParams): InitializeResult => { + return { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode + completionProvider: { triggerCharacters: ["."] }, + }, + }; + } + ); + + connection.onCompletion((textDocumentPosition) => { + return this.provideCompletionItems(textDocumentPosition); + }); + + connection.onRequest( + "connect", + (connectionParams: IConnectionParams) => { + void connectToMongoClient( + connectionParams.connectionString, + connectionParams.extensionUserAgent + ).then((account) => { + this.db = account.db(connectionParams.databaseName); + void this.schemaService + .registerSchemas(this.db) + .then((schemas) => { + this.configureSchemas(schemas); + }); + }); + } + ); + + connection.onRequest("disconnect", () => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.db = null!; + for (const schema of this.schemas) { + this.jsonLanguageService.resetSchema(schema.uri); + } + }); + + this.jsonLanguageService = getLanguageService({ + schemaRequestService: (uri) => + this.schemaService.resolveSchema(uri), + contributions: [], + }); + + this.mongoDocumentsManager = new MongoScriptDocumentManager( + this.schemaService, + this.jsonLanguageService + ); + } + + public provideCompletionItems( + positionParams: TextDocumentPositionParams + ): Promise { + const textDocument = this.textDocuments.get( + positionParams.textDocument.uri + ); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const mongoScriptDocument = this.mongoDocumentsManager.getDocument( + textDocument!, + this.db + ); + return mongoScriptDocument.provideCompletionItemsAt( + positionParams.position + ); + } + + public resetSchema(uri: string): void { + this.jsonLanguageService.resetSchema(uri); + } + + public configureSchemas(schemas: SchemaConfiguration[]): void { + this.jsonLanguageService.configure({ + schemas, + }); + } } diff --git a/Source/mongo/services/mongoScript.ts b/Source/mongo/services/mongoScript.ts index 8d4c85398..4d5cb89dd 100644 --- a/Source/mongo/services/mongoScript.ts +++ b/Source/mongo/services/mongoScript.ts @@ -2,100 +2,133 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, Position } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { SchemaService } from './schemaService'; +import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; +import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; +import { Interval } from "antlr4ts/misc/Interval"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Db } from "mongodb"; +import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; +import { CompletionItem, Position } from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { mongoLexer } from "./../grammar/mongoLexer"; +import * as mongoParser from "./../grammar/mongoParser"; +import { MongoVisitor } from "./../grammar/visitors"; +import { CompletionItemsVisitor } from "./completionItemProvider"; +import { SchemaService } from "./schemaService"; export class MongoScriptDocumentManager { + constructor( + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) {} - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - } - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } + public getDocument( + textDocument: TextDocument, + db: Db + ): MongoScriptDocument { + return new MongoScriptDocument( + textDocument, + db, + this.schemaService, + this.jsonLanguageService + ); + } } export class MongoScriptDocument { + private readonly _lexer: mongoLexer; - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } + constructor( + private textDocument: TextDocument, + private db: Db, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + this._lexer = new mongoLexer(new InputStream(textDocument.getText())); + this._lexer.removeErrorListeners(); + } - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); + public provideCompletionItemsAt( + position: Position + ): Promise { + const parser = new mongoParser.mongoParser( + new CommonTokenStream(this._lexer) + ); + parser.removeErrorListeners(); - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); - } - return Promise.resolve([]); - } + const offset = this.textDocument.offsetAt(position); + const lastNode = new NodeFinder(offset).visit(parser.commands()); + if (lastNode) { + return new CompletionItemsVisitor( + this.textDocument, + this.db, + offset, + this.schemaService, + this.jsonLanguageService + ).visit(lastNode); + } + return Promise.resolve([]); + } } class NodeFinder extends MongoVisitor { + constructor(private offset: number) { + super(); + } - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } + protected defaultResult(ctx: ParseTree): ParseTree { + if (ctx instanceof ParserRuleContext) { + const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; + if (stop < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + if (ctx instanceof TerminalNode) { + if (ctx.symbol.stopIndex < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; - const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; - const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; - const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; + protected aggregateResult( + aggregate: ParseTree, + nextResult: ParseTree + ): ParseTree { + if (aggregate && nextResult) { + const aggregateStart = + aggregate instanceof ParserRuleContext + ? aggregate.start.startIndex + : (aggregate).symbol.startIndex; + const aggregateStop = + aggregate instanceof ParserRuleContext + ? aggregate.start.stopIndex + : (aggregate).symbol.stopIndex; + const nextResultStart = + nextResult instanceof ParserRuleContext + ? nextResult.start.startIndex + : (nextResult).symbol.startIndex; + const nextResultStop = + nextResult instanceof ParserRuleContext + ? nextResult.start.stopIndex + : (nextResult).symbol.stopIndex; - if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } + if ( + Interval.of(aggregateStart, aggregateStop).properlyContains( + Interval.of(nextResultStart, nextResultStop) + ) + ) { + return aggregate; + } + return nextResult; + } + return nextResult ? nextResult : aggregate; + } } diff --git a/Source/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts index cf70e8cde..acb195725 100644 --- a/Source/mongo/services/schemaService.ts +++ b/Source/mongo/services/schemaService.ts @@ -5,624 +5,726 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ -import { Cursor, Db } from 'mongodb'; -import { SchemaConfiguration } from 'vscode-json-languageservice'; +import { Cursor, Db } from "mongodb"; +import { SchemaConfiguration } from "vscode-json-languageservice"; // eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; +import { JSONSchema } from "vscode-json-languageservice/lib/umd/jsonSchema"; export class SchemaService { - - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections() - .then(collections => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push(...[{ - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)] - }, { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)] - }]); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {} - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - for (const property of Object.keys(document)) { - if (!parent && - ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'] - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' - }, - $language: { - type: 'string', - description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' - }, - $caseSensitive: { - type: 'boolean', - description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` - } - }, - required: ['$search'] - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate' - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri - } - }; - schema.properties!.$and = { - type: 'array', - description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri - } - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri - } - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {} - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value' - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value' - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value' - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value' - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value' - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value' - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array' - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array' - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field' - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type' - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0] - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression' - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type' - }, - coordinates: { - type: 'array' - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string' - }, - properties: { - type: 'object' - } - } - } - } - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array' - }, - $polygon: { - type: 'array' - }, - $center: { - type: 'array' - }, - $centerSphere: { - type: 'array' - } - } - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema - } - }; - expressionSchema.properties.$near = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query' - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size' - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties } - }; - schema.properties!.$elemMatch = { - type: 'object' - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view' - } - } - - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri - } - } - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'] - } - }, - additionalProperties: { - type: 'object' - } - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' - } - } - }); - return { - type: 'object', - oneOf: schemas - }; - } - - private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then(hasNext => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then(doc => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } - + private _db: Db; + private _schemasCache: Map = new Map(); + + public registerSchemas(db: Db): Thenable { + this._db = db; + this._schemasCache.clear(); + return this._db.collections().then((collections) => { + const schemas: SchemaConfiguration[] = []; + for (const collection of collections) { + schemas.push( + ...[ + { + uri: this.queryCollectionSchema( + collection.collectionName + ), + fileMatch: [ + this.queryDocumentUri( + collection.collectionName + ), + ], + }, + { + uri: this.aggregateCollectionSchema( + collection.collectionName + ), + fileMatch: [ + this.aggregateDocumentUri( + collection.collectionName + ), + ], + }, + ] + ); + } + return schemas; + }); + } + + public queryCollectionSchema(collectionName: string): string { + return "mongo://query/" + collectionName + ".schema"; + } + + public aggregateCollectionSchema(collectionName: string): string { + return "mongo://aggregate/" + collectionName + ".schema"; + } + + public queryDocumentUri(collectionName: string): string { + return "mongo://query/" + collectionName + ".json"; + } + + public aggregateDocumentUri(collectionName: string): string { + return "mongo://aggregate/" + collectionName + ".json"; + } + + public resolveSchema(uri: string): Thenable { + const schema = this._schemasCache.get(uri); + if (schema) { + return Promise.resolve(schema); + } + if (uri.startsWith("mongo://query/")) { + return this._resolveQueryCollectionSchema( + uri.substring( + "mongo://query/".length, + uri.length - ".schema".length + ), + uri + ).then((sch) => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + if (uri.startsWith("mongo://aggregate/")) { + return this._resolveAggregateCollectionSchema( + uri.substring( + "mongo://aggregate/".length, + uri.length - ".schema".length + ) + ).then((sch) => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + return Promise.resolve(""); + } + + private _resolveQueryCollectionSchema( + collectionName: string, + schemaUri: string + ): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (result) => { + const schema: JSONSchema = { + type: "object", + properties: {}, + }; + for (const document of result) { + this.setSchemaForDocument(null!, document, schema); + } + this.setGlobalOperatorProperties(schema); + this.setLogicalOperatorProperties(schema, schemaUri); + resolve(JSON.stringify(schema)); + }); + }); + } + + private _resolveAggregateCollectionSchema( + collectionName: string + ): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (_result) => { + const schema: JSONSchema = { + type: "array", + items: this.getAggregateStagePropertiesSchema( + this.queryCollectionSchema(collectionName) + ), + }; + resolve(JSON.stringify(schema)); + }); + }); + } + + private getMongoDocumentType(document: any): string { + return Array.isArray(document) + ? "array" + : document === null + ? "null" + : typeof document; + } + + private setSchemaForDocument( + parent: string, + document: any, + schema: JSONSchema + ): void { + if (this.getMongoDocumentType(document) === "object") { + for (const property of Object.keys(document)) { + if (!parent && ["_id"].indexOf(property) !== -1) { + continue; + } + this.setSchemaForDocumentProperty( + parent, + property, + document, + schema + ); + } + } + } + + private setSchemaForDocumentProperty( + parent: string, + property: string, + document: any, + schema: JSONSchema + ): void { + const scopedProperty = parent ? `${parent}.${property}` : property; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const value = document[property]; + const type = this.getMongoDocumentType(value); + + const propertySchema: JSONSchema = { + type: [type, "object"], + }; + this.setOperatorProperties(type, propertySchema); + schema.properties![scopedProperty] = propertySchema; + + if (type === "object") { + this.setSchemaForDocument(scopedProperty, value, schema); + } + + if (type === "array") { + for (const v of value) { + this.setSchemaForDocument(scopedProperty, v, schema); + } + } + } + + private setGlobalOperatorProperties(schema: JSONSchema): void { + schema.properties!.$text = { + type: "object", + description: "Performs text search", + properties: { + $search: { + type: "string", + description: + "A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase", + }, + $language: { + type: "string", + description: + 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming', + }, + $caseSensitive: { + type: "boolean", + description: + "Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index", + }, + $diacriticSensitive: { + type: "boolean", + description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index +Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`, + }, + }, + required: ["$search"], + }; + + schema.properties!.$where = { + type: "string", + description: `Matches documents that satisfy a JavaScript expression. +Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`, + }; + schema.properties!.$comment = { + type: "string", + description: "Adds a comment to a query predicate", + }; + } + + private setLogicalOperatorProperties( + schema: JSONSchema, + schemaUri: string + ): void { + schema.properties!.$or = { + type: "array", + description: + "Joins query clauses with a logical OR returns all documents that match the conditions of either clause", + items: { + $ref: schemaUri, + }, + }; + schema.properties!.$and = { + type: "array", + description: + "Joins query clauses with a logical AND returns all documents that match the conditions of both clauses", + items: { + $ref: schemaUri, + }, + }; + schema.properties!.$nor = { + type: "array", + description: + "Joins query clauses with a logical NOR returns all documents that fail to match both clauses", + items: { + $ref: schemaUri, + }, + }; + } + + private setOperatorProperties(type: string, schema: JSONSchema): void { + if (!schema.properties) { + schema.properties = {}; + } + + const expressionSchema = { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: {}, + }; + // Comparison operators + expressionSchema.properties.$eq = { + type: type, + description: "Matches values that are equal to a specified value", + }; + expressionSchema.properties.$gt = { + type: type, + description: + "Matches values that are greater than a specified value", + }; + expressionSchema.properties.$gte = { + type: type, + description: + "Matches values that are greater than or equal to a specified value", + }; + expressionSchema.properties.$lt = { + type: type, + description: "Matches values that are less than a specified value", + }; + expressionSchema.properties.$lte = { + type: type, + description: + "Matches values that are less than or equal to a specified value", + }; + expressionSchema.properties.$ne = { + type: type, + description: + "Matches all values that are not equal to a specified value", + }; + expressionSchema.properties.$in = { + type: "array", + description: "Matches any of the values specified in an array", + }; + expressionSchema.properties.$nin = { + type: "array", + description: "Matches none of the values specified in an array", + }; + + // Element operators + expressionSchema.properties.$exists = { + type: "boolean", + description: "Matches documents that have the specified field", + }; + expressionSchema.properties.$type = { + type: "string", + description: + "Selects documents if a field is of the specified type", + }; + + // Evaluation operators + expressionSchema.properties.$mod = { + type: "array", + description: + "Performs a modulo operation on the value of a field and selects documents with a specified result", + maxItems: 2, + default: [2, 0], + }; + expressionSchema.properties.$regex = { + type: "string", + description: + "Selects documents where values match a specified regular expression", + }; + + // Geospatial + const geometryPropertySchema: JSONSchema = { + type: "object", + properties: { + type: { + type: "string", + default: "GeoJSON object type", + }, + coordinates: { + type: "array", + }, + crs: { + type: "object", + properties: { + type: { + type: "string", + }, + properties: { + type: "object", + }, + }, + }, + }, + }; + expressionSchema.properties.$geoWithin = { + type: "object", + description: + "Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin", + properties: { + $geometry: geometryPropertySchema, + $box: { + type: "array", + }, + $polygon: { + type: "array", + }, + $center: { + type: "array", + }, + $centerSphere: { + type: "array", + }, + }, + }; + expressionSchema.properties.$geoIntersects = { + type: "object", + description: + "Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects", + properties: { + $geometry: geometryPropertySchema, + }, + }; + expressionSchema.properties.$near = { + type: "object", + description: + "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: "number", + }, + $minDistance: { + type: "number", + }, + }, + }; + expressionSchema.properties.$nearSphere = { + type: "object", + description: + "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: "number", + }, + $minDistance: { + type: "number", + }, + }, + }; + + // Array operatos + if (type === "array") { + expressionSchema.properties.$all = { + type: "array", + description: + "Matches arrays that contain all elements specified in the query", + }; + expressionSchema.properties.$size = { + type: "number", + description: + "Selects documents if the array field is a specified size", + }; + } + + // Bit operators + expressionSchema.properties.$bitsAllSet = { + type: "array", + description: + "Matches numeric or binary values in which a set of bit positions all have a value of 1", + }; + expressionSchema.properties.$bitsAnySet = { + type: "array", + description: + "Matches numeric or binary values in which any bit from a set of bit positions has a value of 1", + }; + expressionSchema.properties.$bitsAllClear = { + type: "array", + description: + "Matches numeric or binary values in which a set of bit positions all have a value of 0", + }; + expressionSchema.properties.$bitsAnyClear = { + type: "array", + description: + "Matches numeric or binary values in which any bit from a set of bit positions has a value of 0", + }; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + schema.properties = { ...expressionSchema.properties }; + schema.properties!.$not = { + type: "object", + description: + "Inverts the effect of a query expression and returns documents that do not match the query expression", + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: { ...expressionSchema.properties }, + }; + schema.properties!.$elemMatch = { + type: "object", + }; + } + + private getAggregateStagePropertiesSchema( + querySchemaUri: string + ): JSONSchema { + const schemas: JSONSchema[] = []; + schemas.push({ + type: "object", + properties: { + $collStats: { + type: "object", + description: + "Returns statistics regarding a collection or view", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $project: { + type: "object", + description: + "Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $match: { + type: "object", + description: + "Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)", + $ref: querySchemaUri, + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $redact: { + type: "object", + description: + "Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $limit: { + type: "object", + description: + "Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $skip: { + type: "object", + description: + "Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $unwind: { + type: "object", + description: + "Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $group: { + type: "object", + description: + "Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.", + properties: { + _id: { + type: ["string", "object"], + }, + }, + additionalProperties: { + type: "object", + }, + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sample: { + type: "object", + description: + "Randomly selects the specified number of documents from its input", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sort: { + type: "object", + description: + "Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $geoNear: { + type: "object", + description: + "Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $lookup: { + type: "object", + description: + "Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $out: { + type: "object", + description: + "Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $indexStats: { + type: "object", + description: + "Returns statistics regarding the use of each index for the collection", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $facet: { + type: "object", + description: + "Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $bucket: { + type: "object", + description: + "Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $bucketAuto: { + type: "object", + description: + "Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sortByCount: { + type: "object", + description: + "Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $addFields: { + type: "object", + description: + "Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $replaceRoot: { + type: "object", + description: + "Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $count: { + type: "object", + description: + "Returns a count of the number of documents at this stage of the aggregation pipeline", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $graphLookup: { + type: "object", + description: + "Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document", + }, + }, + }); + return { + type: "object", + oneOf: schemas, + }; + } + + private readNext( + result: any[], + cursor: Cursor, + batchSize: number, + callback: (result: any[]) => void + ): void { + if (result.length === batchSize) { + callback(result); + return; + } + + void cursor.hasNext().then((hasNext) => { + if (!hasNext) { + callback(result); + return; + } + + void cursor.next().then((doc) => { + result.push(doc); + this.readNext(result, cursor, batchSize, callback); + }); + }); + } } diff --git a/Source/mongo/setConnectedNode.ts b/Source/mongo/setConnectedNode.ts index f5680d09d..bcb8e95e1 100644 --- a/Source/mongo/setConnectedNode.ts +++ b/Source/mongo/setConnectedNode.ts @@ -6,8 +6,10 @@ import { ext } from "../extensionVariables"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); +export function setConnectedNode( + node: MongoDatabaseTreeItem | undefined +): void { + ext.connectedMongoDB = node; + const dbName = node && node.label; + ext.mongoCodeLensProvider.setConnectedDatabase(dbName); } diff --git a/Source/mongo/tree/IMongoTreeRoot.ts b/Source/mongo/tree/IMongoTreeRoot.ts index d9b68980d..262e03876 100644 --- a/Source/mongo/tree/IMongoTreeRoot.ts +++ b/Source/mongo/tree/IMongoTreeRoot.ts @@ -1,9 +1,8 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ export interface IMongoTreeRoot { - isEmulator: boolean | undefined; + isEmulator: boolean | undefined; } diff --git a/Source/mongo/tree/MongoAccountTreeItem.ts b/Source/mongo/tree/MongoAccountTreeItem.ts index baa870c23..2f4621afb 100644 --- a/Source/mongo/tree/MongoAccountTreeItem.ts +++ b/Source/mongo/tree/MongoAccountTreeItem.ts @@ -3,138 +3,191 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; -import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + AzExtTreeItem, + ICreateChildImplContext, + parseError, +} from "@microsoft/vscode-azext-utils"; +import { MongoClient } from "mongodb"; +import * as vscode from "vscode"; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; +import { getThemeAgnosticIconPath, Links, testDb } from "../../constants"; +import { nonNullProp } from "../../utils/nonNull"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { getDatabaseNameFromConnectionString } from "../mongoConnectionStrings"; +import { IMongoTreeRoot } from "./IMongoTreeRoot"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; +import { MongoDatabaseTreeItem } from "./MongoDatabaseTreeItem"; +import { MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error('Missing connection string'); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); - - const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [{ - name: databaseInConnectionString, - empty: false - }]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); - databases = result.databases; - } - return databases - .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty - .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } - finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createMongoDatabase', - validateInput: validateDatabaseName - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public static contextValue: string = "cosmosDBMongoServer"; + public readonly contextValue: string = MongoAccountTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly label: string; + public readonly connectionString: string; + + private _root: IMongoTreeRoot; + + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + connectionString: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super(parent); + this.id = id; + this.label = label; + this.connectionString = connectionString; + this._root = { isEmulator }; + this.valuesToMask.push(connectionString); + } + + // overrides ISubscriptionContext with an object that also has Mongo info + public get root(): IMongoTreeRoot { + return this._root; + } + + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("CosmosDBAccount.svg"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + let mongoClient: MongoClient | undefined; + try { + let databases: IDatabaseInfo[]; + + if (!this.connectionString) { + throw new Error("Missing connection string"); + } + + // Azure MongoDB accounts need to have the name passed in for private endpoints + mongoClient = await connectToMongoClient( + this.connectionString, + this.databaseAccount + ? nonNullProp(this.databaseAccount, "name") + : appendExtensionUserAgent() + ); + + const databaseInConnectionString = + getDatabaseNameFromConnectionString(this.connectionString); + if (databaseInConnectionString && !this.root.isEmulator) { + // emulator violates the connection string format + // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) + databases = [ + { + name: databaseInConnectionString, + empty: false, + }, + ]; + } else { + // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: { databases: IDatabaseInfo[] } = await mongoClient + .db(testDb) + .admin() + .listDatabases(); + databases = result.databases; + } + return databases + .filter( + (database: IDatabaseInfo) => + !( + database.name && + database.name.toLowerCase() === "admin" && + database.empty + ) + ) // Filter out the 'admin' database if it's empty + .map( + (database) => + new MongoDatabaseTreeItem( + this, + nonNullProp(database, "name"), + this.connectionString + ) + ); + } catch (error) { + const message = parseError(error).message; + if (this._root.isEmulator && message.includes("ECONNREFUSED")) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; + } + throw error; + } finally { + if (mongoClient) { + void mongoClient.close(); + } + } + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: "createMongoDatabase", + validateInput: validateDatabaseName, + }); + context.showCreatingTreeItem(databaseName); + + return new MongoDatabaseTreeItem( + this, + databaseName, + this.connectionString + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case MongoDatabaseTreeItem.contextValue: + case MongoCollectionTreeItem.contextValue: + case MongoDocumentTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } } -export function validateDatabaseName(database: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return "Database name cannot contain these characters - `/\\. \"$#?=`"; - } - return undefined; +export function validateDatabaseName( + database: string +): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions + // "#?" are restricted characters for CosmosDB - MongoDB accounts + const min = 1; + const max = 63; + if (!database || database.length < min || database.length > max) { + return `Database name must be between ${min} and ${max} characters.`; + } + if (/[/\\. "$#?=]/.test(database)) { + return 'Database name cannot contain these characters - `/\\. "$#?=`'; + } + return undefined; } export interface IDatabaseInfo { - name?: string; - empty?: boolean; + name?: string; + empty?: boolean; } diff --git a/Source/mongo/tree/MongoCollectionTreeItem.ts b/Source/mongo/tree/MongoCollectionTreeItem.ts index eca0c8d32..b4dd4f68f 100644 --- a/Source/mongo/tree/MongoCollectionTreeItem.ts +++ b/Source/mongo/tree/MongoCollectionTreeItem.ts @@ -5,316 +5,473 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullValue } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { MongoCommand } from '../MongoCommand'; -import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as assert from "assert"; +import { + BulkWriteOpResultObject, + Collection, + CollectionInsertManyOptions, + Cursor, + DeleteWriteOpResultObject, + InsertOneWriteOpResult, + InsertWriteOpResult, + MongoCountPreferences, +} from "mongodb"; +import * as _ from "underscore"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullValue } from "../../utils/nonNull"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { getBatchSizeSetting } from "../../utils/workspacUtils"; +import { MongoCommand } from "../MongoCommand"; +import { IMongoDocument, MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; type MongoDocument = { _id: string }; class FunctionDescriptor { - public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { - } + public constructor( + public mongoFunction: MongoFunction, + public text: string, + public minShellArgs: number, + public maxShellArgs: number, + public maxHandledArgs: number + ) {} } -export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, '_id'), - upsert: false - } - }; - }); - - const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = await this.getCachedChildren(context); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(children.map(c => c.document), null, 2); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get filePath(): string { - return this.label + '-cosmos-collection.json'; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { - const documentNodes = await this.getCachedChildren(context); - for (const doc of docs) { - const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection.find(this._query).batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - 'invalidMongoDocument', - doc => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; - - const functions = { - drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), - count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), - findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), - insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), - insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), - insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), - deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), - deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), - remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error(`Too few arguments passed to command ${command.name}.`); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error(`Too many arguments passed to command ${command.name}`); - } - if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number, name?: string } = e; - const NamespaceNotFoundCode = 26; - if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne(query?: Object, fieldsOption?: Object): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, '\t'); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error("The insert command requires at least one argument"); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count(query?: Object[], options?: MongoCountPreferences): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, '\t'); - } +export class MongoCollectionTreeItem + extends AzExtParentTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "MongoCollection"; + public readonly contextValue: string = MongoCollectionTreeItem.contextValue; + public readonly childTypeLabel: string = "Document"; + public readonly collection: Collection; + public parent: AzExtParentTreeItem; + public findArgs?: {}[]; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + + private readonly _query: object | undefined; + private readonly _projection: object | undefined; + private _cursor: Cursor | undefined; + private _hasMoreChildren: boolean = true; + private _batchSize: number = getBatchSizeSetting(); + + constructor( + parent: AzExtParentTreeItem, + collection: Collection, + findArgs?: {}[] + ) { + super(parent); + this.collection = collection; + this.findArgs = findArgs; + if (findArgs && findArgs.length) { + this._query = findArgs[0]; + this._projection = findArgs.length > 1 ? findArgs[1] : undefined; + } + ext.fileSystem.fireChangedEvent(this); + } + + public async writeFileContent( + context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const documents: IMongoDocument[] = EJSON.parse(content); + const operations = documents.map((document) => { + return { + replaceOne: { + filter: { _id: document._id }, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + replacement: _.omit(document, "_id"), + upsert: false, + }, + }; + }); + + const result: BulkWriteOpResultObject = + await this.collection.bulkWrite(operations); + ext.outputChannel.appendLog( + `Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)` + ); + + // The current tree item may have been a temporary one used to execute a scrapbook command. + // We want to refresh children for this one _and_ the actual one in the tree (if it's different) + const nodeInTree: MongoCollectionTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); + const nodesToRefresh: MongoCollectionTreeItem[] = [this]; + if (nodeInTree && this !== nodeInTree) { + nodesToRefresh.push(nodeInTree); + } + + await Promise.all( + nodesToRefresh.map((n) => n.refreshChildren(context, documents)) + ); + + if (nodeInTree && this !== nodeInTree) { + // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different + ext.fileSystem.fireChangedEvent(nodeInTree); + } + } + + public async getFileContent(context: IActionContext): Promise { + const children = ( + await this.getCachedChildren(context) + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify( + children.map((c) => c.document), + null, + 2 + ); + } + + public get id(): string { + return this.collection.collectionName; + } + + public get label(): string { + return this.collection.collectionName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get filePath(): string { + return this.label + "-cosmos-collection.json"; + } + + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + ext.fileSystem.fireChangedEvent(this); + } + + public async refreshChildren( + context: IActionContext, + docs: IMongoDocument[] + ): Promise { + const documentNodes = ( + await this.getCachedChildren(context) + ); + for (const doc of docs) { + const documentNode = documentNodes.find( + (node) => node.document._id.toString() === doc._id.toString() + ); + if (documentNode) { + documentNode.document = doc; + await documentNode.refresh(context); + } + } + } + + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } + + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache || this._cursor === undefined) { + this._cursor = this.collection + .find(this._query) + .batchSize(this._batchSize); + if (this._projection) { + this._cursor = this._cursor.project(this._projection); + } + } + + const documents: IMongoDocument[] = []; + let count: number = 0; + while (count < this._batchSize) { + this._hasMoreChildren = await this._cursor.hasNext(); + if (this._hasMoreChildren) { + documents.push(await this._cursor.next()); + count += 1; + } else { + break; + } + } + this._batchSize *= 2; + + return this.createTreeItemsWithErrorHandling( + documents, + "invalidMongoDocument", + (doc) => new MongoDocumentTreeItem(this, doc), + getDocumentTreeItemLabel + ); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + context.showCreatingTreeItem(""); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: InsertOneWriteOpResult = + await this.collection.insertOne({}); + const newDocument: IMongoDocument = nonNullValue( + await this.collection.findOne({ _id: result.insertedId }), + "newDocument" + ); + return new MongoDocumentTreeItem(this, newDocument); + } + + public async tryExecuteCommandDirectly( + command: Partial + ): Promise< + | { deferToShell: true; result: undefined } + | { deferToShell: false; result: string } + > { + // range and text are not neccessary properties for this function so partial should suffice + const parameters = command.arguments + ? command.arguments.map(parseJSContent) + : []; + + const functions = { + drop: new FunctionDescriptor( + this.drop, + "Dropping collection", + 0, + 0, + 0 + ), + count: new FunctionDescriptor( + this.count, + "Counting documents", + 0, + 2, + 2 + ), + findOne: new FunctionDescriptor( + this.findOne, + "Finding document", + 0, + 2, + 2 + ), + insert: new FunctionDescriptor( + this.insert, + "Inserting document", + 1, + 1, + 1 + ), + insertMany: new FunctionDescriptor( + this.insertMany, + "Inserting documents", + 1, + 2, + 2 + ), + insertOne: new FunctionDescriptor( + this.insertOne, + "Inserting document", + 1, + 2, + 2 + ), + deleteMany: new FunctionDescriptor( + this.deleteMany, + "Deleting documents", + 1, + 2, + 1 + ), + deleteOne: new FunctionDescriptor( + this.deleteOne, + "Deleting document", + 1, + 2, + 1 + ), + remove: new FunctionDescriptor( + this.remove, + "Deleting document(s)", + 1, + 2, + 1 + ), + }; + + // eslint-disable-next-line no-prototype-builtins + if (command.name && functions.hasOwnProperty(command.name)) { + // currently no logic to handle chained commands so just defer to the shell right away + if (command.chained) { + return { deferToShell: true, result: undefined }; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const descriptor: FunctionDescriptor = functions[command.name]; + + if (parameters.length < descriptor.minShellArgs) { + throw new Error( + `Too few arguments passed to command ${command.name}.` + ); + } + if (parameters.length > descriptor.maxShellArgs) { + throw new Error( + `Too many arguments passed to command ${command.name}` + ); + } + if (parameters.length > descriptor.maxHandledArgs) { + //this function won't handle these arguments, but the shell will + return { deferToShell: true, result: undefined }; + } + const result = await reportProgress( + descriptor.mongoFunction.apply(this, parameters), + descriptor.text + ); + return { deferToShell: false, result }; + } + return { deferToShell: true, result: undefined }; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoCollection" }, + DialogResponses.deleteResponse + ); + await this.drop(); + } + + private async drop(): Promise { + try { + await this.collection.drop(); + return `Dropped collection '${this.collection.collectionName}'.`; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const error: { code?: number; name?: string } = e; + const NamespaceNotFoundCode = 26; + if ( + error.name === "MongoError" && + error.code === NamespaceNotFoundCode + ) { + return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; + } else { + throw error; + } + } + } + + private async findOne( + query?: Object, + fieldsOption?: Object + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = await this.collection.findOne(query || {}, { + fields: fieldsOption, + }); + // findOne is the only command in this file whose output requires EJSON support. + // Hence that's the only function which uses EJSON.stringify rather than this.stringify. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(result, null, "\t"); + } + + private async insert(document: Object): Promise { + if (!document) { + throw new Error( + "The insert command requires at least one argument" + ); + } + + const insertResult = await this.collection.insert(document); + return this.stringify(insertResult); + } + + private async insertOne(document: Object, options?: any): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const insertOneResult: InsertOneWriteOpResult = + await this.collection.insertOne(document, { + w: options && options.writeConcern, + }); + return this.stringify(insertOneResult); + } + + private async insertMany(documents: any[], options?: any): Promise { + assert.notEqual( + documents.length, + 0, + "Array of documents cannot be empty" + ); + const insertManyOptions: CollectionInsertManyOptions = {}; + if (options) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.ordered) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.ordered = options.ordered; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.writeConcern) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.w = options.writeConcern; + } + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const insertManyResult: InsertWriteOpResult = + await this.collection.insertMany(documents, insertManyOptions); + return this.stringify(insertManyResult); + } + + private async remove(filter: Object): Promise { + const removeResult = await this.collection.remove(filter); + return this.stringify(removeResult); + } + + private async deleteOne(filter: Object): Promise { + const deleteOneResult: DeleteWriteOpResultObject = + await this.collection.deleteOne(filter); + return this.stringify(deleteOneResult); + } + + private async deleteMany(filter: Object): Promise { + const deleteOpResult: DeleteWriteOpResultObject = + await this.collection.deleteMany(filter); + return this.stringify(deleteOpResult); + } + + private async count( + query?: Object[], + options?: MongoCountPreferences + ): Promise { + const count = await this.collection.count(query, options); + return this.stringify(count); + } + + private stringify(result: any): string { + return JSON.stringify(result, null, "\t"); + } } function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title - }, - (_progress) => { - return promise; - }); + return vscode.window.withProgress( + { + location: vscode.ProgressLocation.Window, + title: title, + }, + (_progress) => { + return promise; + } + ); } function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.parse(content); + } catch (error) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + throw error.message; + } } diff --git a/Source/mongo/tree/MongoDatabaseTreeItem.ts b/Source/mongo/tree/MongoDatabaseTreeItem.ts index 73a7c6a22..1fed13c80 100644 --- a/Source/mongo/tree/MongoDatabaseTreeItem.ts +++ b/Source/mongo/tree/MongoDatabaseTreeItem.ts @@ -3,256 +3,383 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import { Collection, Db, DbCollectionOptions } from 'mongodb'; -import * as path from 'path'; -import * as process from 'process'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { MongoCommand } from '../MongoCommand'; -import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; -import { MongoShell } from '../MongoShell'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoAccountTreeItem } from './MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, + UserCancelledError, +} from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import { Collection, Db, DbCollectionOptions } from "mongodb"; +import * as path from "path"; +import * as process from "process"; +import * as vscode from "vscode"; +import { ext } from "../../extensionVariables"; +import * as cpUtils from "../../utils/cp"; +import { nonNullProp, nonNullValue } from "../../utils/nonNull"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { MongoCommand } from "../MongoCommand"; +import { addDatabaseToAccountConnectionString } from "../mongoConnectionStrings"; +import { MongoShell } from "../MongoShell"; +import { IMongoTreeRoot } from "./IMongoTreeRoot"; +import { MongoAccountTreeItem } from "./MongoAccountTreeItem"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; + +const mongoExecutableFileName = + process.platform === "win32" ? "mongo.exe" : "mongo"; const executingInShellMsg = "Executing command in Mongo shell"; export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map(collection => new MongoCollectionTreeItem(this, collection)); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: 'createMongoCollection', - validateInput: validateMongoCollectionName - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); - return accountConnection.db(this.databaseName); - } - - public async executeCommand(command: MongoCommand, context: IActionContext): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); - const result = await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - - } - - if (command.name === 'createCollection') { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); - } else { - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - } - } - - public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection(collectionName, options); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); - - if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); - return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); - } - - private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongo', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongo'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; - const browse: vscode.MessageItem = { title: 'Open installation page' }; - const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; - const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; - const tryAgain: vscode.MessageItem = { title: 'Try again' }; - const response2 = await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } + public static contextValue: string = "mongoDb"; + public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; + public readonly connectionString: string; + public readonly databaseName: string; + public readonly parent: MongoAccountTreeItem; + + private _previousShellPathSetting: string | undefined; + private _cachedShellPathOrCmd: string | undefined; + + constructor( + parent: MongoAccountTreeItem, + databaseName: string, + connectionString: string + ) { + super(parent); + this.databaseName = databaseName; + this.connectionString = addDatabaseToAccountConnectionString( + connectionString, + this.databaseName + ); + } + + public get root(): IMongoTreeRoot { + return this.parent.root; + } + + public get label(): string { + return this.databaseName; + } + + public get description(): string { + return ext.connectedMongoDB && + ext.connectedMongoDB.fullId === this.fullId + ? "Connected" + : ""; + } + + public get id(): string { + return this.databaseName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("database"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const db: Db = await this.connectToDb(); + const collections: Collection[] = await db.collections(); + return collections.map( + (collection) => new MongoCollectionTreeItem(this, collection) + ); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const collectionName = await context.ui.showInputBox({ + placeHolder: "Collection Name", + prompt: "Enter the name of the collection", + stepName: "createMongoCollection", + validateInput: validateMongoCollectionName, + }); + + context.showCreatingTreeItem(collectionName); + return await this.createCollection(collectionName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoDatabase" }, + DialogResponses.deleteResponse + ); + const db = await this.connectToDb(); + await db.dropDatabase(); + } + + public async connectToDb(): Promise { + const accountConnection = await connectToMongoClient( + this.connectionString, + appendExtensionUserAgent() + ); + return accountConnection.db(this.databaseName); + } + + public async executeCommand( + command: MongoCommand, + context: IActionContext + ): Promise { + if (command.collection) { + const db = await this.connectToDb(); + const collection = db.collection(command.collection); + if (collection) { + const collectionTreeItem = new MongoCollectionTreeItem( + this, + collection, + command.arguments + ); + const result = + await collectionTreeItem.tryExecuteCommandDirectly(command); + if (!result.deferToShell) { + return result.result; + } + } + return withProgress( + this.executeCommandInShell(command, context), + executingInShellMsg + ); + } + + if (command.name === "createCollection") { + // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead + return withProgress( + this.createCollection( + stripQuotes(nonNullProp(command, "arguments")[0]), + nonNullProp(command, "argumentObjects")[1] + ).then(() => JSON.stringify({ Created: "Ok" })), + "Creating collection" + ); + } else { + return withProgress( + this.executeCommandInShell(command, context), + executingInShellMsg + ); + } + } + + public async createCollection( + collectionName: string, + options?: DbCollectionOptions + ): Promise { + const db: Db = await this.connectToDb(); + const newCollection: Collection = await db.createCollection( + collectionName, + options + ); + // db.createCollection() doesn't create empty collections for some reason + // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection + const result = await newCollection.insertOne({}); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + await newCollection.deleteOne({ _id: result.insertedId }); + return new MongoCollectionTreeItem(this, newCollection); + } + + private async executeCommandInShell( + command: MongoCommand, + context: IActionContext + ): Promise { + context.telemetry.properties.executeInShell = "true"; + + if (this.root.isEmulator) { + // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info + await this.connectToDb(); + } + + // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state + // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out + // requests. + const shell = await this.createShell(context); + try { + await shell.useDatabase(this.databaseName); + return await shell.executeScript(command.text); + } finally { + shell.dispose(); + } + } + + private async createShell(context: IActionContext): Promise { + const config = vscode.workspace.getConfiguration(); + let shellPath: string | undefined = config.get( + ext.settingsKeys.mongoShellPath + ); + const shellArgs: string[] = config.get( + ext.settingsKeys.mongoShellArgs, + [] + ); + + if ( + !shellPath || + !this._cachedShellPathOrCmd || + this._previousShellPathSetting !== shellPath + ) { + // Only do this if setting changed since last time + shellPath = await this._determineShellPathOrCmd(context, shellPath); + this._previousShellPathSetting = shellPath; + } + this._cachedShellPathOrCmd = shellPath; + + const timeout = + 1000 * + nonNullValue( + config.get(ext.settingsKeys.mongoShellTimeout), + "mongoShellTimeout" + ); + return MongoShell.create( + shellPath, + shellArgs, + this.connectionString, + this.root.isEmulator, + ext.outputChannel, + timeout + ); + } + + private async _determineShellPathOrCmd( + context: IActionContext, + shellPathSetting: string | undefined + ): Promise { + if (!shellPathSetting) { + // User hasn't specified the path + if (await cpUtils.commandSucceeds("mongo", "--version")) { + // If the user already has mongo in their system path, just use that + return "mongo"; + } else { + // If all else fails, prompt the user for the mongo path + const openFile: vscode.MessageItem = { + title: `Browse to ${mongoExecutableFileName}`, + }; + const browse: vscode.MessageItem = { + title: "Open installation page", + }; + const noMongoError: string = + "This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting."; + const response = await context.ui.showWarningMessage( + noMongoError, + { stepName: "promptForMongoPath" }, + browse, + openFile + ); + if (response === openFile) { + // eslint-disable-next-line no-constant-condition + while (true) { + const newPath: vscode.Uri[] = + await context.ui.showOpenDialog({ + filters: { + "Executable Files": [ + process.platform === "win32" + ? "exe" + : "", + ], + }, + openLabel: `Select ${mongoExecutableFileName}`, + stepName: "openMongoExeFile", + }); + const fsPath = newPath[0].fsPath; + const baseName = path.basename(fsPath); + if (baseName !== mongoExecutableFileName) { + const useAnyway: vscode.MessageItem = { + title: "Use anyway", + }; + const tryAgain: vscode.MessageItem = { + title: "Try again", + }; + const response2 = + await context.ui.showWarningMessage( + `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, + { stepName: "confirmMongoExeFile" }, + useAnyway, + tryAgain + ); + if (response2 === tryAgain) { + continue; + } + } + + await vscode.workspace + .getConfiguration() + .update( + ext.settingsKeys.mongoShellPath, + fsPath, + vscode.ConfigurationTarget.Global + ); + return fsPath; + } + } else if (response === browse) { + void vscode.commands.executeCommand( + "vscode.open", + vscode.Uri.parse( + "https://docs.mongodb.com/manual/installation/" + ) + ); + // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath + } + + throw new UserCancelledError("createShell"); + } + } else { + // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix + if (await fse.pathExists(shellPathSetting)) { + const stat = await fse.stat(shellPathSetting); + if (stat.isDirectory()) { + return path.join(shellPathSetting, mongoExecutableFileName); + } + } + + return shellPathSetting; + } + } } -export function validateMongoCollectionName(collectionName: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; +export function validateMongoCollectionName( + collectionName: string +): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names + if (!collectionName) { + return "Collection name cannot be empty"; + } + const systemPrefix = "system."; + if (collectionName.startsWith(systemPrefix)) { + return `"${systemPrefix}" prefix is reserved for internal use`; + } + if (/[$]/.test(collectionName)) { + return "Collection name cannot contain $"; + } + return undefined; } -function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title - }, - (_progress) => { - return promise; - }); +function withProgress( + promise: Thenable, + title: string, + location: vscode.ProgressLocation = vscode.ProgressLocation.Window +): Thenable { + return vscode.window.withProgress( + { + location: location, + title: title, + }, + (_progress) => { + return promise; + } + ); } export function stripQuotes(term: string): string { - if ((term.startsWith('\'') && term.endsWith('\'')) - || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; + if ( + (term.startsWith("'") && term.endsWith("'")) || + (term.startsWith('"') && term.endsWith('"')) + ) { + return term.substring(1, term.length - 1); + } + return term; } diff --git a/Source/mongo/tree/MongoDocumentTreeItem.ts b/Source/mongo/tree/MongoDocumentTreeItem.ts index ad44e43c3..dae87ed84 100644 --- a/Source/mongo/tree/MongoDocumentTreeItem.ts +++ b/Source/mongo/tree/MongoDocumentTreeItem.ts @@ -3,95 +3,131 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { + Collection, + DeleteWriteOpResultObject, + ObjectID, + UpdateWriteOpResult, +} from "mongodb"; +import * as _ from "underscore"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); export interface IMongoDocument { - _id: string | ObjectID; + _id: string | ObjectID; - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + // custom properties + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [key: string]: any; } -export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); +export class MongoDocumentTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "MongoDocument"; + public readonly contextValue: string = MongoDocumentTreeItem.contextValue; + public document: IMongoDocument; + public readonly parent: MongoCollectionTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); - private _label: string; + private _label: string; - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = 'cosmosDB.openDocument'; - ext.fileSystem.fireChangedEvent(this); - } + constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { + super(parent); + this.document = document; + this._label = getDocumentTreeItemLabel(this.document); + this.commandId = "cosmosDB.openDocument"; + ext.fileSystem.fireChangedEvent(this); + } - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } + public get id(): string { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return String(this.document!._id); + } - public get label(): string { - return this._label; - } + public get label(): string { + return this._label; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("file"); + } - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } + public get filePath(): string { + return this.label + "-cosmos-document.json"; + } - public static async update(collection: Collection, newDocument: IMongoDocument): Promise { - if (!newDocument._id) { - throw new Error(`The "_id" field is required to update a document.`); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); - if (result.modifiedCount !== 1) { - throw new Error(`Failed to update document with _id '${newDocument._id}'.`); - } - return newDocument; - } + public static async update( + collection: Collection, + newDocument: IMongoDocument + ): Promise { + if (!newDocument._id) { + throw new Error( + `The "_id" field is required to update a document.` + ); + } + const filter: object = { _id: newDocument._id }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const result: UpdateWriteOpResult = await collection.replaceOne( + filter, + _.omit(newDocument, "_id") + ); + if (result.modifiedCount !== 1) { + throw new Error( + `Failed to update document with _id '${newDocument._id}'.` + ); + } + return newDocument; + } - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } + public async getFileContent(): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(this.document, null, 2); + } - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this.document); + ext.fileSystem.fireChangedEvent(this); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); - const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error(`Failed to delete document with _id '${this.document._id}'.`); - } - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this._label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoDocument" }, + DialogResponses.deleteResponse + ); + const deleteResult: DeleteWriteOpResultObject = + await this.parent.collection.deleteOne({ _id: this.document._id }); + if (deleteResult.deletedCount !== 1) { + throw new Error( + `Failed to delete document with _id '${this.document._id}'.` + ); + } + } - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); - } + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const newDocument: IMongoDocument = EJSON.parse(content); + this.document = await MongoDocumentTreeItem.update( + this.parent.collection, + newDocument + ); + } } diff --git a/Source/postgres/abstract/AbstractPostgresClient.ts b/Source/postgres/abstract/AbstractPostgresClient.ts index c1fa29c4f..ca6bd3d9a 100644 --- a/Source/postgres/abstract/AbstractPostgresClient.ts +++ b/Source/postgres/abstract/AbstractPostgresClient.ts @@ -6,18 +6,26 @@ import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; +import { + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../../utils/azureClients"; import { PostgresServerType } from "./models"; -export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; +export type AbstractPostgresClient = + | PostgreSQLFlexibleManagementClient + | PostgreSQLSingleManagementClient; -export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context) - case PostgresServerType.Single: - return await createPostgreSQLClient(context) - default: - throw new Error("Service not implemented."); - } +export async function createAbstractPostgresClient( + serverType: PostgresServerType, + context: AzExtClientContext +): Promise { + switch (serverType) { + case PostgresServerType.Flexible: + return await createPostgreSQLFlexibleClient(context); + case PostgresServerType.Single: + return await createPostgreSQLClient(context); + default: + throw new Error("Service not implemented."); + } } diff --git a/Source/postgres/abstract/models.ts b/Source/postgres/abstract/models.ts index 6bdadf16a..046185de1 100644 --- a/Source/postgres/abstract/models.ts +++ b/Source/postgres/abstract/models.ts @@ -7,49 +7,58 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; export enum PostgresServerType { - Flexible = 'Flexible', - Single = 'Single' + Flexible = "Flexible", + Single = "Single", } -export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } +export type PostgresAbstractServer = ( + | SingleModels.Server + | FlexibleModels.Server +) & { serverType?: PostgresServerType }; -export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; +export type PostgresAbstractDatabase = + | SingleModels.Database + | FlexibleModels.Database; /** * Billing information related properties of a server. */ export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; + /** + * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + */ + name: string; + /** + * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', + * 'GeneralPurpose', 'MemoryOptimized' + */ + tier: SingleModels.SkuTier | FlexibleModels.SkuTier; + /** + * The scale up/out capacity, representing server's compute units. + */ + capacity?: number; + /** + * The size code, to be interpreted by resource as appropriate. + */ + size?: string; + /** + * The family of hardware. + */ + family?: string; } export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; + location: string; + sku: AbstractSku; + administratorLogin: string; + administratorLoginPassword: string; + size: number; } -export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; +export type AbstractNameAvailability = + | SingleModels.NameAvailability + | FlexibleModels.NameAvailability; -export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; +export type AbstractFirewallRule = + | SingleModels.FirewallRule + | FlexibleModels.FirewallRule; diff --git a/Source/postgres/commands/checkAuthentication.ts b/Source/postgres/commands/checkAuthentication.ts index 6799d060c..c26bc25be 100644 --- a/Source/postgres/commands/checkAuthentication.ts +++ b/Source/postgres/commands/checkAuthentication.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; +import { + IActionContext, + IParsedError, + parseError, +} from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; import { invalidCredentialsErrorType } from "../postgresConstants"; import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; @@ -11,26 +15,34 @@ import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; import { configurePostgresFirewall } from "./configurePostgresFirewall"; import { enterPostgresCredentials } from "./enterPostgresCredentials"; -export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); +export async function checkAuthentication( + context: IActionContext, + treeItem: PostgresDatabaseTreeItem +): Promise { + let clientConfig: ClientConfig | undefined; + while (!clientConfig) { + const isFirewallRuleSet = + await treeItem.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + await configurePostgresFirewall(context, treeItem.parent); + continue; + } + try { + const getClientConfigResult = + await PostgresClientConfigFactory.getClientConfigFromNode( + treeItem.parent, + treeItem.databaseName + ); + clientConfig = getClientConfigResult.clientConfig; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; + if (parsedError.errorType === invalidCredentialsErrorType) { + await enterPostgresCredentials(context, treeItem.parent); + } else { + throw error; + } + } + } + return clientConfig; } diff --git a/Source/postgres/commands/configurePostgresFirewall.ts b/Source/postgres/commands/configurePostgresFirewall.ts index 52a378fca..86779ff9b 100644 --- a/Source/postgres/commands/configurePostgresFirewall.ts +++ b/Source/postgres/commands/configurePostgresFirewall.ts @@ -4,66 +4,102 @@ *--------------------------------------------------------------------------------------------*/ import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { getPublicIpv4 } from "../../utils/getIp"; import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; +import { nonNullProp } from "../../utils/nonNull"; +import { randomUtils } from "../../utils/randomUtils"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../abstract/AbstractPostgresClient"; +import { AbstractFirewallRule, PostgresServerType } from "../abstract/models"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function configurePostgresFirewall( + context: IActionContext, + treeItem?: PostgresServerTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), - { - modal: true, - stepName: 'postgresAddFirewallRule' - }, - { title: DialogResponses.yes.title } - ); + const ip: string = await getPublicIp(context); + await context.ui.showWarningMessage( + localize( + "firewallRuleWillBeAdded", + 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', + ip, + treeItem.label + ), + { + modal: true, + stepName: "postgresAddFirewallRule", + }, + { title: DialogResponses.yes.title } + ); - await setFirewallRule(context, treeItem, ip); + await setFirewallRule(context, treeItem, ip); } -export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { +export async function setFirewallRule( + context: IActionContext, + treeItem: PostgresServerTreeItem, + ip: string +): Promise { + const serverType: PostgresServerType = nonNullProp(treeItem, "serverType"); + const client: AbstractPostgresClient = await createAbstractPostgresClient( + serverType, + [context, treeItem.subscription] + ); + const resourceGroup: string = nonNullProp(treeItem, "resourceGroup"); + const serverName: string = nonNullProp(treeItem, "azureName"); - const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); - const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); - const serverName: string = nonNullProp(treeItem, 'azureName'); + const firewallRuleName: string = + "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; + const newFirewallRule: AbstractFirewallRule = { + startIpAddress: ip, + endIpAddress: ip, + }; - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip - }; - - const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); - }); - const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); + const progressMessage: string = localize( + "configuringFirewallRule", + 'Adding firewall rule for IP "{0}" to server "{1}"...', + ip, + serverName + ); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage, + }; + ext.outputChannel.appendLog(progressMessage); + await vscode.window.withProgress(options, async () => { + await client.firewallRules.beginCreateOrUpdateAndWait( + resourceGroup, + serverName, + firewallRuleName, + newFirewallRule + ); + }); + const completedMessage: string = localize( + "addedFirewallRule", + 'Successfully added firewall rule for IP "{0}" to server "{1}".', + ip, + serverName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + await treeItem.refresh(context); } export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); + return await getPublicIpv4(context); } diff --git a/Source/postgres/commands/connectPostgresDatabase.ts b/Source/postgres/commands/connectPostgresDatabase.ts index 6996f7d03..9437c8c70 100644 --- a/Source/postgres/commands/connectPostgresDatabase.ts +++ b/Source/postgres/commands/connectPostgresDatabase.ts @@ -4,36 +4,52 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from 'vscode'; -import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { Uri, window } from "vscode"; +import { + connectedPostgresKey, + postgresFlexibleFilter, + postgresSingleFilter, +} from "../../constants"; import { ext } from "../../extensionVariables"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } +export async function connectPostgresDatabase( + context: IActionContext, + treeItem?: Uri | PostgresDatabaseTreeItem +): Promise { + if (!treeItem || treeItem instanceof Uri) { + if (treeItem) { + void window.showTextDocument(treeItem); + } + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); + const oldTreeItemId: string | undefined = + ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; + void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); + ext.connectedPostgresDB = treeItem; + const database = treeItem && treeItem.label; + if (ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(database); + } + await treeItem.refresh(context); - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } + if (oldTreeItemId) { + // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldTreeItem: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + oldTreeItemId, + context + ); + if (oldTreeItem) { + await oldTreeItem.refresh(context); + } + } } diff --git a/Source/postgres/commands/copyConnectionString.ts b/Source/postgres/commands/copyConnectionString.ts index 716bbd5b6..6d9bcbcf2 100644 --- a/Source/postgres/commands/copyConnectionString.ts +++ b/Source/postgres/commands/copyConnectionString.ts @@ -3,34 +3,56 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { + addDatabaseToConnectionString, + copyPostgresConnectionString, +} from "../postgresConnectionStrings"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { checkAuthentication } from "./checkAuthentication"; -export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } +export async function copyConnectionString( + context: IActionContext, + node: PostgresDatabaseTreeItem +): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); - } else { - connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); - } + await checkAuthentication(context, node); + const parsedConnectionString = await node.parent.getFullConnectionString(); + let connectionString: string; + if (node.parent.azureName) { + const parsedCS = await node.parent.getFullConnectionString(); + connectionString = copyPostgresConnectionString( + parsedCS.hostName, + parsedCS.port, + parsedCS.username, + parsedCS.password, + node.databaseName + ); + } else { + connectionString = addDatabaseToConnectionString( + parsedConnectionString.connectionString, + node.databaseName + ); + } - await vscode.env.clipboard.writeText(connectionString); - const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); - void vscode.window.showInformationMessage(message); + await vscode.env.clipboard.writeText(connectionString); + const message = localize( + "copiedPostgresConnectStringMsg", + "The connection string has been copied to the clipboard" + ); + void vscode.window.showInformationMessage(message); } diff --git a/Source/postgres/commands/createPostgresDatabase.ts b/Source/postgres/commands/createPostgresDatabase.ts index 6c096a52b..c86e5ac45 100644 --- a/Source/postgres/commands/createPostgresDatabase.ts +++ b/Source/postgres/commands/createPostgresDatabase.ts @@ -3,24 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -import { connectPostgresDatabase } from './connectPostgresDatabase'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; +import { connectPostgresDatabase } from "./connectPostgresDatabase"; -export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); +export async function createPostgresDatabase( + context: IActionContext, + node?: PostgresServerTreeItem +): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } + const newDatabase: PostgresDatabaseTreeItem = + await node.createChild(context); + await connectPostgresDatabase(context, newDatabase); + const createMessage: string = localize( + "createPostgresDatabaseMsg", + 'Successfully created database "{0}".', + newDatabase.databaseName + ); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); } diff --git a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts index 81d54b9af..64a4fe0b5 100644 --- a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -7,6 +6,6 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; + name?: string; + query?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts index 27b32993c..8b4dd5f93 100644 --- a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts @@ -5,6 +5,7 @@ import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; -export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { - returnType?: string; +export interface IPostgresFunctionQueryWizardContext + extends IPostgresQueryWizardContext { + returnType?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts index 8c4df098b..ca281d4d4 100644 --- a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts @@ -11,13 +11,19 @@ import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; -export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], - executeSteps: [new FunctionQueryCreateStep()], - title: 'Create PostgreSQL Function Query' - }); +export async function createPostgresFunctionQuery( + context: IActionContext, + treeItem?: PostgresFunctionsTreeItem +): Promise { + const wizardContext: IPostgresFunctionQueryWizardContext = context; + const wizard = new AzureWizard(wizardContext, { + promptSteps: [ + new FunctionQueryNameStep(), + new FunctionQueryReturnTypeStep(), + ], + executeSteps: [new FunctionQueryCreateStep()], + title: "Create PostgreSQL Function Query", + }); - await runPostgresQueryWizard(wizard, wizardContext, treeItem); + await runPostgresQueryWizard(wizard, wizardContext, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts index 9356882d9..9c0bd1e34 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts @@ -9,18 +9,26 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresFunctionQueryWizardContext): Promise { - context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); - } + public async execute( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.query = defaultFunctionQuery( + nonNullProp(context, "name"), + nonNullProp(context, "returnType") + ); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) +const defaultFunctionQuery = ( + name: string, + returnType: string +) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) RETURNS ${returnType} LANGUAGE plpgsql AS $function$ diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts index cfacc0f64..a37c18995 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts @@ -8,11 +8,18 @@ import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); - } + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.returnType = await context.ui.showInputBox({ + prompt: localize( + "provideCustomReturnType", + "Provide custom return type" + ), + }); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts index 36d798074..78459f842 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts @@ -9,14 +9,21 @@ import { validateIdentifier } from "../../validateIdentifier"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideFunctionName', 'Provide function name'), - validateInput: validateIdentifier - })).trim(); - } + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.name = ( + await context.ui.showInputBox({ + prompt: localize( + "provideFunctionName", + "Provide function name" + ), + validateInput: validateIdentifier, + }) + ).trim(); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts index 63f703793..b69c94a2c 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts @@ -3,48 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, + IWizardOptions, +} from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); - returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + const returnTypeQuickPicks: IAzureQuickPickItem[] = + returnTypes.map((r) => { + return { label: r, data: r }; + }); + returnTypeQuickPicks.push({ + label: localize( + "enterCustomReturnType", + "$(pencil) Enter custom return type..." + ), + data: undefined, + }); - context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize('selectReturnType', 'Select return type') - })).data; - } + context.returnType = ( + await context.ui.showQuickPick(returnTypeQuickPicks, { + placeHolder: localize("selectReturnType", "Select return type"), + }) + ).data; + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } - public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { - return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } + public async getSubWizard( + context: IPostgresFunctionQueryWizardContext + ): Promise< + IWizardOptions | undefined + > { + return context.returnType + ? undefined + : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; + } } // A subset of return types available on pgAdmin const returnTypes: string[] = [ - 'bigint', - 'bigint[]', - 'boolean', - 'boolean[]', - 'character', - 'character[]', - 'date', - 'date[]', - 'integer', - 'integer[]', - 'json', - 'json[]', - 'oid', - 'oid[]', - 'smallint', - 'smallint[]', - 'text', - 'void' + "bigint", + "bigint[]", + "boolean", + "boolean[]", + "character", + "character[]", + "date", + "date[]", + "integer", + "integer[]", + "json", + "json[]", + "oid", + "oid[]", + "smallint", + "smallint[]", + "text", + "void", ]; diff --git a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts index 925695e56..65288da3d 100644 --- a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts @@ -4,20 +4,31 @@ *--------------------------------------------------------------------------------------------*/ import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; +import { + postgresBaseFileName, + postgresFileExtension, +} from "../../../constants"; import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from '../../../utils/vscodeUtils'; +import * as vscodeUtil from "../../../utils/vscodeUtils"; import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; import { connectPostgresDatabase } from "../connectPostgresDatabase"; import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; -export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); +export async function runPostgresQueryWizard( + wizard: AzureWizard, + context: IPostgresQueryWizardContext, + treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem +): Promise { + await wizard.prompt(); + await wizard.execute(); + await vscodeUtil.showNewFile( + nonNullProp(context, "query"), + postgresBaseFileName, + postgresFileExtension + ); - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } + if (treeItem) { + await connectPostgresDatabase(context, treeItem.parent); + } } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts index f1ddbe51b..b63bf39ae 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts @@ -9,12 +9,15 @@ import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; -export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: 'Create PostgreSQL Stored Procedure Query' - }); +export async function createPostgresStoredProcedureQuery( + context: IActionContext, + treeItem?: PostgresStoredProceduresTreeItem +): Promise { + const wizard = new AzureWizard(context, { + promptSteps: [new StoredProcedureQueryNameStep()], + executeSteps: [new StoredProcedureQueryCreateStep()], + title: "Create PostgreSQL Stored Procedure Query", + }); - await runPostgresQueryWizard(wizard, context, treeItem); + await runPostgresQueryWizard(wizard, context, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts index 2cf3ef916..67bbbbf0c 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts @@ -9,18 +9,22 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); - } + public async execute(context: IPostgresQueryWizardContext): Promise { + context.query = defaultStoredProcedureQuery( + nonNullProp(context, "name") + ); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) +const defaultStoredProcedureQuery = ( + name: string +) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) LANGUAGE plpgsql AS $$ BEGIN diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts index bf9a00392..5b694f378 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts @@ -9,14 +9,19 @@ import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; import { validateIdentifier } from "../../validateIdentifier"; export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), - validateInput: validateIdentifier - })).trim(); - } + public async prompt(context: IPostgresQueryWizardContext): Promise { + context.name = ( + await context.ui.showInputBox({ + prompt: localize( + "provideStoredProcedureName", + "Provide stored procedure name" + ), + validateInput: validateIdentifier, + }) + ).trim(); + } - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts index 9339f6796..94bb16657 100644 --- a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts @@ -6,108 +6,123 @@ import { localize } from "../../../utils/localize"; export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); + // Identifier naming rules: https://aka.ms/AA8618j + identifier = identifier.trim(); - const min = 1; - const max = 63; + const min = 1; + const max = 63; - if (identifier.length < min || identifier.length > max) { - return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } + if (identifier.length < min || identifier.length > max) { + return localize( + "postgresResourcesNameLengthCheck", + "The name must be between {0} and {1} characters.", + min, + max + ); + } - if (!identifier[0].match(/[a-z_]/i)) { - return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); - } + if (!identifier[0].match(/[a-z_]/i)) { + return localize( + "mustStartWithLetterOrUnderscore", + "Name must start with a letter or underscore." + ); + } - if (identifier.match(/[^a-z_\d$]/i)) { - return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); - } + if (identifier.match(/[^a-z_\d$]/i)) { + return localize( + "canOnlyContainCertainCharacters", + "Name can only contain letters, underscores, digits (0-9), and dollar signs ($)." + ); + } - if (reservedWords.has(identifier.toLowerCase())) { - return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); - } + if (reservedWords.has(identifier.toLowerCase())) { + return localize( + "cantBeReservedWord", + 'Name cannot be reserved word "{0}".', + identifier + ); + } - return undefined; + return undefined; } // Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html const reservedWords: Set = new Set([ - 'all', - 'analyse', - 'analyze', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'asymmetric', - 'both', - 'case', - 'cast', - 'check', - 'collate', - 'column', - 'constraint', - 'create', - 'current_catalog', - 'current_date', - 'current_role', - 'current_time', - 'current_timestamp', - 'current_user', - 'default', - 'deferrable', - 'desc', - 'distinct', - 'do', - 'else', - 'end', - 'except', - 'false', - 'fetch', - 'for', - 'foreign', - 'from', - 'grant', - 'group', - 'having', - 'in', - 'initially', - 'intersect', - 'into', - 'lateral', - 'leading', - 'limit', - 'localtime', - 'localtimestamp', - 'not', - 'null', - 'offset', - 'on', - 'only', - 'or', - 'order', - 'placing', - 'primary', - 'references', - 'returning', - 'select', - 'session_user', - 'some', - 'symmetric', - 'table', - 'then', - 'to', - 'trailing', - 'true', - 'union', - 'unique', - 'user', - 'using', - 'variadic', - 'when', - 'where', - 'window', - 'with' + "all", + "analyse", + "analyze", + "and", + "any", + "array", + "as", + "asc", + "asymmetric", + "both", + "case", + "cast", + "check", + "collate", + "column", + "constraint", + "create", + "current_catalog", + "current_date", + "current_role", + "current_time", + "current_timestamp", + "current_user", + "default", + "deferrable", + "desc", + "distinct", + "do", + "else", + "end", + "except", + "false", + "fetch", + "for", + "foreign", + "from", + "grant", + "group", + "having", + "in", + "initially", + "intersect", + "into", + "lateral", + "leading", + "limit", + "localtime", + "localtimestamp", + "not", + "null", + "offset", + "on", + "only", + "or", + "order", + "placing", + "primary", + "references", + "returning", + "select", + "session_user", + "some", + "symmetric", + "table", + "then", + "to", + "trailing", + "true", + "union", + "unique", + "user", + "using", + "variadic", + "when", + "where", + "window", + "with", ]); diff --git a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts index 390c1cf42..cc28cd581 100644 --- a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts @@ -5,20 +5,26 @@ import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; +import { + AbstractSku, + PostgresAbstractServer, + PostgresServerType, +} from "../../abstract/models"; -export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; +export interface IPostgresServerWizardContext + extends IAzureDBWizardContext, + ExecuteActivityContext { + /** + * Username without server, i.e. "user1" + */ + shortUserName?: string; + /** + * Username with server, i.e. "user1@server1" + */ + longUserName?: string; + adminPassword?: string; - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; + server?: PostgresAbstractServer; + sku?: AbstractSku; + serverType?: PostgresServerType; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts index 2f07d8203..20d13ffbf 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts @@ -8,24 +8,30 @@ import { localize } from "../../../../utils/localize"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize('confirmPW', 'Confirm your password'); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) - }); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const prompt: string = localize("confirmPW", "Confirm your password"); + await context.ui.showInputBox({ + prompt, + password: true, + validateInput: async ( + value: string | undefined + ): Promise => + await this.validatePassword(context, value), + }); + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !!context.adminPassword; + } - private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { - if (passphrase !== context.adminPassword) { - return localize('pwMatch', 'The passwords must match.'); - } + private async validatePassword( + context: IPostgresServerWizardContext, + passphrase: string | undefined + ): Promise { + if (passphrase !== context.adminPassword) { + return localize("pwMatch", "The passwords must match."); + } - return undefined; - } + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts index f73ce810d..549f1e67f 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts @@ -5,100 +5,133 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; +import { + AzureWizardExecuteStep, + callWithMaskHandling, +} from "@microsoft/vscode-azext-utils"; import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { Progress } from "vscode"; +import { ext } from "../../../../extensionVariables"; +import { + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../../../../utils/azureClients"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + AbstractServerCreate, + PostgresServerType, +} from "../../../abstract/models"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; + public priority: number = 150; - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + public async execute( + context: IPostgresServerWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + const locationName: string = ( + await LocationListStep.getLocation(context) + ).name; + const rgName: string = nonNullProp( + nonNullProp(context, "resourceGroup"), + "name" + ); + const size: string = nonNullProp(nonNullProp(context, "sku"), "size"); + const newServerName = nonNullProp(context, "newServerName"); + const password: string = nonNullProp(context, "adminPassword"); - const locationName: string = (await LocationListStep.getLocation(context)).name; - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); - const newServerName = nonNullProp(context, 'newServerName'); - const password: string = nonNullProp(context, 'adminPassword'); + return await callWithMaskHandling(async () => { + const serverType = nonNullProp(context, "serverType"); + const createMessage: string = localize( + "creatingPostgresServer", + 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', + context.newServerName + ); - return await callWithMaskHandling( - async () => { - const serverType = nonNullProp(context, 'serverType'); - const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); + ext.outputChannel.appendLog(createMessage); + progress.report({ message: createMessage }); + const options: AbstractServerCreate = { + location: locationName, + sku: nonNullProp(context, "sku"), + administratorLogin: nonNullProp(context, "shortUserName"), + administratorLoginPassword: password, + size: parseInt(size), + }; - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, 'sku'), - administratorLogin: nonNullProp(context, 'shortUserName'), - administratorLoginPassword: password, - size: parseInt(size) - }; + switch (serverType) { + case PostgresServerType.Single: + const singleClient: SingleModels.PostgreSQLManagementClient = + await createPostgreSQLClient(context); + context.server = + await singleClient.servers.beginCreateAndWait( + rgName, + newServerName, + this.asSingleParameters(options) + ); + break; + case PostgresServerType.Flexible: + const flexiClient: FlexibleModels.PostgreSQLManagementClient = + await createPostgreSQLFlexibleClient(context); + context.server = + await flexiClient.servers.beginCreateAndWait( + rgName, + newServerName, + this.asFlexibleParameters(options) + ); + break; + } + context.server.serverType = serverType; + context.activityResult = context.server as AppResource; + }, password); + } - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); - context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); - context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, - password); - } + public shouldExecute(context: IPostgresServerWizardContext): boolean { + return !context.server; + } - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } - - - private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier - }, - } - } - - private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size - } - } - } - } + private asFlexibleParameters( + parameters: AbstractServerCreate + ): FlexibleModels.Server { + return { + location: parameters.location, + version: "12", + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + storage: { + storageSizeGB: parameters.size, + }, + sku: { + name: parameters.sku.name, + tier: parameters.sku.tier, + }, + }; + } + private asSingleParameters( + parameters: AbstractServerCreate + ): SingleModels.ServerForCreate { + return { + location: parameters.location, + sku: { + name: parameters.sku.name, + capacity: parameters.sku.capacity, + size: parameters.sku.size, + family: parameters.sku.family, + tier: parameters.sku.tier as SingleModels.SkuTier, + }, + properties: { + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: + parameters.administratorLoginPassword, + sslEnforcement: "Enabled", + createMode: "Default", + version: "11", + storageProfile: { + storageMB: parameters.size, + }, + }, + }; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts index c48d40c37..dd5c84c25 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts @@ -3,51 +3,66 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; -const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); +const pwConditionMsg = localize( + "passwordConditionMsg", + "Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.)." +); export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, 'shortUserName'); - context.adminPassword = (await context.ui.showInputBox({ - placeHolder: localize('pwPlaceholder', 'Administrator Password'), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => validatePassword(user, password), - })); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const user = nonNullProp(context, "shortUserName"); + context.adminPassword = await context.ui.showInputBox({ + placeHolder: localize("pwPlaceholder", "Administrator Password"), + prompt: pwConditionMsg, + password: true, + validateInput: (password: string) => + validatePassword(user, password), + }); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.adminPassword; + } } -async function validatePassword(username: string, password: string): Promise { - password = password ? password : ''; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map(substring => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); - } else { - return undefined; - } +async function validatePassword( + username: string, + password: string +): Promise { + password = password ? password : ""; + + const min = 8; + const max = 128; + + const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; + let numOccurrence = 0; + + regex.map((substring) => { + if (password.match(substring)) { + numOccurrence++; + } + }); + + if (password.length < min || password.length > max) { + return localize( + "pwLengthCheck", + "Password must be between {0} and {1} characters.", + min, + max + ); + } else if (numOccurrence < 3) { + return pwConditionMsg; + } else if (password.includes(username)) { + return localize( + "pwUserSimalarityCheck", + "Password cannot contain the username." + ); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts index 7b4890d07..14b7de8f7 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts @@ -3,46 +3,80 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = (await context.ui.showInputBox({ - placeHolder: localize('usernamePlaceholder', 'Administrator Username'), - validateInput: validateUser, - })).trim(); - const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; - context.longUserName = context.shortUserName + usernameSuffix; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + context.shortUserName = ( + await context.ui.showInputBox({ + placeHolder: localize( + "usernamePlaceholder", + "Administrator Username" + ), + validateInput: validateUser, + }) + ).trim(); + const usernameSuffix: string = `@${nonNullProp( + context, + "newServerName" + )}`; + context.longUserName = context.shortUserName + usernameSuffix; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.shortUserName; + } } async function validateUser(username: string): Promise { - username = username ? username.trim() : ''; + username = username ? username.trim() : ""; - const min = 1; - const max = 63; + const min = 1; + const max = 63; - const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; + const restricted = [ + "azure_superuser", + "azure_pg_admin", + "admin", + "administrator", + "root", + "guest", + "public", + ]; - if (username.length < min || username.length > max) { - return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); - } else if (username.match(/^[0-9]+/)) { - return localize('usernameBeginningMatch', 'The name cannot start with a number.'); - } else if (username.toLowerCase().startsWith('pg_')) { - return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map(d => `"${d}"`).join(', '); - return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); - } else { - return undefined; - } + if (username.length < min || username.length > max) { + return localize( + "usernameLenghtMatch", + "The name must be between {0} and {1} characters.", + min, + max + ); + } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { + return localize( + "usernameCharacterCheck", + 'The name can only contain letters, numbers, and the "_" character.' + ); + } else if (username.match(/^[0-9]+/)) { + return localize( + "usernameBeginningMatch", + "The name cannot start with a number." + ); + } else if (username.toLowerCase().startsWith("pg_")) { + return localize( + "usernameStartWithCheck", + 'Admin username cannot start with "pg_".' + ); + } else if (restricted.includes(username.toLowerCase())) { + const restrictedString = restricted.map((d) => `"${d}"`).join(", "); + return localize( + "usernameRestrictedCheck", + "Admin username cannot be any of the following: {0}.", + restrictedString + ); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts index 1af03f5c7..76b25373e 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts @@ -3,58 +3,111 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; -import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { + ResourceGroupListStep, + resourceGroupNamingRules, +} from "@microsoft/vscode-azext-azureutils"; +import { AzureNameStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../../../abstract/AbstractPostgresClient"; +import { + AbstractNameAvailability, + PostgresServerType, +} from "../../../abstract/models"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerNameStep extends AzureNameStep { + public async prompt(context: IPostgresServerWizardContext): Promise { + const client = await createAbstractPostgresClient( + nonNullProp(context, "serverType"), + context + ); + context.newServerName = ( + await context.ui.showInputBox({ + placeHolder: localize("serverNamePlaceholder", "Server name"), + prompt: localize( + "enterServerNamePrompt", + "Provide a name for the PostgreSQL Server." + ), + validateInput: (name: string) => + validatePostgresServerName( + name, + client, + nonNullProp(context, "serverType") + ), + }) + ).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName( + context, + context.newServerName, + resourceGroupNamingRules + ); + } - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: localize('serverNamePlaceholder', 'Server name'), - prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), - validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.newServerName; + } -async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { - name = name ? name.trim() : ''; + protected async isRelatedNameAvailable( + context: IPostgresServerWizardContext, + name: string + ): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } +} - const min = 3; - const max = 63; +async function validatePostgresServerName( + name: string, + client: AbstractPostgresClient, + serverType: PostgresServerType +): Promise { + name = name ? name.trim() : ""; - if (name.length < min || name.length > max) { - return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } else if (!(/^[a-z0-9-]+$/).test(name)) { - return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); - } else if (name.startsWith('-') || name.endsWith('-')) { - return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); - } - const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); + const min = 3; + const max = 63; - if (!availability.nameAvailable) { - return availability.message ? - availability.message : - localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); - } + if (name.length < min || name.length > max) { + return localize( + "serverNameLengthCheck", + "The name must be between {0} and {1} characters.", + min, + max + ); + } else if (!/^[a-z0-9-]+$/.test(name)) { + return localize( + "serverNameCharacterCheck", + "Server name must only contain lowercase letters, numbers, and hyphens." + ); + } else if (name.startsWith("-") || name.endsWith("-")) { + return localize( + "serverNamePrefixSuffixCheck", + "Server name must not start or end in a hyphen." + ); + } + const resourceType = + serverType === PostgresServerType.Single + ? "Microsoft.DBforPostgreSQL" + : "Microsoft.DBforPostgreSQL/flexibleServers"; + const availability: AbstractNameAvailability = + await client.checkNameAvailability.execute({ + name: name, + type: resourceType, + }); - return undefined; + if (!availability.nameAvailable) { + return availability.message + ? availability.message + : localize( + "serverNameAvailabilityCheck", + 'Server name "{0}" is not available.', + name + ); + } + return undefined; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts index 3431e8f00..e93027936 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts @@ -3,44 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; -import { setPostgresCredentials } from '../../setPostgresCredentials'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { Progress } from "vscode"; +import { ext } from "../../../../extensionVariables"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + PostgresAbstractServer, + PostgresServerType, +} from "../../../abstract/models"; +import { setPostgresCredentials } from "../../setPostgresCredentials"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; + public priority: number = 200; - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + public async execute( + context: IPostgresServerWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + let user: string; + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexbile Server instance + if ( + context.serverType && + context.serverType === PostgresServerType.Single + ) { + user = nonNullProp(context, "longUserName"); + } else { + user = nonNullProp(context, "shortUserName"); + } + const newServerName: string = nonNullProp(context, "newServerName"); - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if (context.serverType && context.serverType === PostgresServerType.Single) { - user = nonNullProp(context, 'longUserName'); - } else { - user = nonNullProp(context, 'shortUserName'); - } - const newServerName: string = nonNullProp(context, 'newServerName'); + const setupMessage: string = localize( + "setupCredentialsMessage", + 'Setting up Credentials for server "{0}"...', + newServerName + ); + progress.report({ message: setupMessage }); + ext.outputChannel.appendLog(setupMessage); + const password: string = nonNullProp(context, "adminPassword"); + const server: PostgresAbstractServer = nonNullProp(context, "server"); - const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, 'adminPassword'); - const server: PostgresAbstractServer = nonNullProp(context, 'server'); + await setPostgresCredentials(user, password, nonNullProp(server, "id")); + const completedMessage: string = localize( + "addedCredentialsMessage", + 'Successfully setup credentials for server "{0}".', + newServerName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + } - await setPostgresCredentials(user, password, nonNullProp(server, 'id')); - const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } - - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts index 654cd0430..3efe5e223 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts @@ -2,7 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, +} from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../utils/localize"; import { nonNullProp } from "../../../../utils/nonNull"; import { openUrl } from "../../../../utils/openUrl"; @@ -10,241 +13,257 @@ import { AbstractSku, PostgresServerType } from "../../../abstract/models"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; + label: string; + description: string; + sku: AbstractSku; + group?: string; } export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresServerWizardContext - ): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); - pricingTiers.push({ - label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), - onPicked: async () => { - await openUrl('https://aka.ms/AAcxhvm'); - }, data: undefined - }); + public async prompt(context: IPostgresServerWizardContext): Promise { + const placeHolder: string = localize( + "selectPostgresSku", + "Select the Postgres SKU and options." + ); + const pricingTiers: IAzureQuickPickItem[] = + await this.getPicks(nonNullProp(context, "serverType")); + pricingTiers.push({ + label: localize( + "ShowPricingCalculator", + "$(link-external) Show pricing information..." + ), + onPicked: async () => { + await openUrl("https://aka.ms/AAcxhvm"); + }, + data: undefined, + }); - context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; - } + context.sku = ( + await context.ui.showQuickPick(pricingTiers, { + placeHolder, + suppressPersistence: true, + enableGrouping: true, + }) + ).data; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return context.sku === undefined; + } - public async getPicks(serverType: PostgresServerType): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; + public async getPicks( + serverType: PostgresServerType + ): Promise[]> { + const options: IAzureQuickPickItem[] = []; + const skuOptions: ISkuOption[] = + serverType === PostgresServerType.Single + ? singleServerSkus + : flexibleServerSkus; - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: option.group || localize('addlOptions', 'Additional Options') - }); - }); - return options; - } + skuOptions.forEach((option) => { + options.push({ + label: option.label, + description: localize( + nonNullProp(option.sku, "name"), + option.description + ), + data: option.sku, + group: + option.group || + localize("addlOptions", "Additional Options"), + }); + }); + return options; + } } -const recommendedGroup = localize('recommendGroup', 'Recommended'); +const recommendedGroup = localize("recommendGroup", "Recommended"); const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, + { + label: "B1", + description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", + sku: { + name: "B_Gen5_1", + tier: "Basic", + capacity: 1, + family: "Gen5", + size: "5120", + }, + group: recommendedGroup, + }, + { + label: "B2", + description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", + sku: { + name: "B_Gen5_2", + tier: "Basic", + capacity: 2, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP2", + description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_2", + tier: "GeneralPurpose", + capacity: 2, + family: "Gen5", + size: "51200", + }, + group: recommendedGroup, + }, + { + label: "GP4", + description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_4", + tier: "GeneralPurpose", + capacity: 4, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP8", + description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_8", + tier: "GeneralPurpose", + capacity: 8, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP16", + description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_16", + tier: "GeneralPurpose", + capacity: 16, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP32", + description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_32", + tier: "GeneralPurpose", + capacity: 32, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP64", + description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_64", + tier: "GeneralPurpose", + capacity: 64, + family: "Gen5", + size: "204800", + }, + }, ]; // Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 // See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, + { + label: "B1ms", + description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", + sku: { + name: "Standard_B1ms", + tier: "Burstable", + capacity: 1, + size: "32", + }, + group: recommendedGroup, + }, + { + label: "B2s", + description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", + sku: { + name: "Standard_B2s", + tier: "Burstable", + capacity: 2, + size: "32", + }, + }, + { + label: "D2s_v3", + description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", + sku: { + name: "Standard_D2s_v3", + tier: "GeneralPurpose", + capacity: 2, + size: "32", + }, + group: recommendedGroup, + }, + { + label: "D4s_v3", + description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", + sku: { + name: "Standard_D4s_v3", + tier: "GeneralPurpose", + capacity: 4, + size: "32", + }, + }, + { + label: "D8s_v3", + description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", + sku: { + name: "Standard_D8s_v3", + tier: "GeneralPurpose", + capacity: 8, + size: "64", + }, + }, + { + label: "D16s_v3", + description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", + sku: { + name: "Standard_D16s_v3", + tier: "GeneralPurpose", + capacity: 16, + size: "64", + }, + }, + { + label: "D32s_v3", + description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", + sku: { + name: "Standard_D32s_v3", + tier: "GeneralPurpose", + capacity: 32, + size: "64", + }, + }, + { + label: "D48s_v3", + description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", + sku: { + name: "Standard_D48s_v3", + tier: "GeneralPurpose", + capacity: 48, + size: "256", + }, + }, + { + label: "D64s_v3", + description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", + sku: { + name: "Standard_D64s_v3", + tier: "GeneralPurpose", + capacity: 64, + size: "256", + }, + }, ]; diff --git a/Source/postgres/commands/deletePostgresDatabase.ts b/Source/postgres/commands/deletePostgresDatabase.ts index a09520bde..705b8823f 100644 --- a/Source/postgres/commands/deletePostgresDatabase.ts +++ b/Source/postgres/commands/deletePostgresDatabase.ts @@ -3,28 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); - const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresDatabase( + context: IActionContext, + node?: PostgresDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } + const message: string = localize( + "deletesPostgresDatabase", + 'Are you sure you want to delete database "{0}"?', + node.databaseName + ); + const result = await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresDatabase" }, + DialogResponses.deleteResponse + ); + if (result === DialogResponses.deleteResponse) { + await node.deleteTreeItem(context); + } + const deleteMessage: string = localize( + "deletePostgresDatabaseMsg", + 'Successfully deleted database "{0}".', + node.databaseName + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresFunction.ts b/Source/postgres/commands/deletePostgresFunction.ts index 9a4547428..9ee7a21d7 100644 --- a/Source/postgres/commands/deletePostgresFunction.ts +++ b/Source/postgres/commands/deletePostgresFunction.ts @@ -3,27 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } +export async function deletePostgresFunction( + context: IActionContext, + treeItem?: PostgresFunctionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresFunctionTreeItem.contextValue, + } + ); + } - const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize( + "deleteFunction", + 'Are you sure you want to delete function "{0}"?', + treeItem.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresFunction" }, + DialogResponses.deleteResponse + ); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedFunction", + 'Successfully deleted function "{0}".', + treeItem.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresServer.ts b/Source/postgres/commands/deletePostgresServer.ts index 733c6fca6..686b3c134 100644 --- a/Source/postgres/commands/deletePostgresServer.ts +++ b/Source/postgres/commands/deletePostgresServer.ts @@ -3,20 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; -import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; +import { + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { deleteDatabaseAccount } from "../../commands/deleteDatabaseAccount/deleteDatabaseAccount"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function deletePostgresServer( + context: IActionContext, + node?: PostgresServerTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - await deleteDatabaseAccount(context, node, true) + await deleteDatabaseAccount(context, node, true); } diff --git a/Source/postgres/commands/deletePostgresStoredProcedure.ts b/Source/postgres/commands/deletePostgresStoredProcedure.ts index 6abece79b..244a207d2 100644 --- a/Source/postgres/commands/deletePostgresStoredProcedure.ts +++ b/Source/postgres/commands/deletePostgresStoredProcedure.ts @@ -3,27 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; +import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } +export async function deletePostgresStoredProcedure( + context: IActionContext, + treeItem?: PostgresStoredProcedureTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = + await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresStoredProcedureTreeItem.contextValue, + } + ); + } - const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize( + "deleteStoredProcedure", + 'Are you sure you want to delete stored procedure "{0}"?', + treeItem.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresStoredProcedure" }, + DialogResponses.deleteResponse + ); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedStoredProcedure", + 'Successfully deleted stored procedure "{0}".', + treeItem.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresTable.ts b/Source/postgres/commands/deletePostgresTable.ts index bfdce33a2..60cfb0c18 100644 --- a/Source/postgres/commands/deletePostgresTable.ts +++ b/Source/postgres/commands/deletePostgresTable.ts @@ -3,26 +3,48 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; -export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); - await node.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresTable( + context: IActionContext, + node?: PostgresTableTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresTableTreeItem.contextValue, + } + ); + } + const message: string = localize( + "deletesPostgresTable", + 'Are you sure you want to delete table "{0}"?', + node.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresTable" }, + DialogResponses.deleteResponse + ); + await node.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedTable", + 'Successfully deleted table "{0}".', + node.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/enterPostgresCredentials.ts b/Source/postgres/commands/enterPostgresCredentials.ts index aa993c337..ff146d290 100644 --- a/Source/postgres/commands/enterPostgresCredentials.ts +++ b/Source/postgres/commands/enterPostgresCredentials.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { PostgresServerType } from '../abstract/models'; +import { nonNullProp } from "../../utils/nonNull"; +import { PostgresServerType } from "../abstract/models"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; import { setPostgresCredentials } from "./setPostgresCredentials"; @@ -17,69 +17,118 @@ import { setPostgresCredentials } from "./setPostgresCredentials"; * Get the username and password for the Postgres database from user input. */ async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string, password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), - stepName: 'enterPostgresUsername', - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } - }); + context: IActionContext, + serverType: PostgresServerType, + serverName: string, + serverDisplayName: string +): Promise<{ username: string; password: string }> { + let username: string = await context.ui.showInputBox({ + prompt: localize( + "enterUsername", + 'Enter username for server "{0}"', + serverDisplayName + ), + stepName: "enterPostgresUsername", + validateInput: (value: string) => { + return value && value.length + ? undefined + : localize( + "usernameCannotBeEmpty", + "Username cannot be empty." + ); + }, + }); - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { - username += usernameSuffix; - } + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexible Server instance + const usernameSuffix: string = `@${serverName}`; + if ( + serverType === PostgresServerType.Single && + !username.includes(usernameSuffix) + ) { + username += usernameSuffix; + } - const password: string = await context.ui.showInputBox({ - prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), - stepName: 'enterPostgresPassword', - password: true, - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } - }); + const password: string = await context.ui.showInputBox({ + prompt: localize( + "enterPassword", + 'Enter password for server "{0}"', + serverDisplayName + ), + stepName: "enterPostgresPassword", + password: true, + validateInput: (value: string) => { + return value && value.length + ? undefined + : localize( + "passwordCannotBeEmpty", + "Password cannot be empty." + ); + }, + }); - return { username, password }; + return { username, password }; } /** * Save the username and password in secure local storage. */ -async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { - const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; +async function persistUsernamePassword( + id: string, + serverName: string, + username: string, + password: string +): Promise { + const progressMessage: string = localize( + "setupCredentialsMessage", + 'Setting up credentials for server "{0}"...', + serverName + ); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage, + }; - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); + await vscode.window.withProgress(options, async () => { + await setPostgresCredentials(username, password, id); + }); - const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); + const completedMessage: string = localize( + "setupCredentialsMessage", + 'Successfully added credentials to server "{0}".', + serverName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); } -export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function enterPostgresCredentials( + context: IActionContext, + treeItem?: PostgresServerTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, 'azureName'); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, 'id'); + const serverType = treeItem.serverType; + const serverName: string = nonNullProp(treeItem, "azureName"); + const serverDisplayName: string = treeItem.label; + const id: string = nonNullProp(treeItem, "id"); - const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); + const { username, password } = await getUsernamePassword( + context, + serverType, + serverName, + serverDisplayName + ); - await persistUsernamePassword(id, serverName, username, password); + await persistUsernamePassword(id, serverName, username, password); - treeItem.setCredentials(username, password); - await treeItem.refresh(context); + treeItem.setCredentials(username, password); + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/executePostgresQueryInDocument.ts b/Source/postgres/commands/executePostgresQueryInDocument.ts index af5d3ca5e..4aedb847b 100644 --- a/Source/postgres/commands/executePostgresQueryInDocument.ts +++ b/Source/postgres/commands/executePostgresQueryInDocument.ts @@ -3,63 +3,92 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { EOL } from 'os'; -import * as path from 'path'; -import { ClientConfig, QueryResult } from 'pg'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import * as vscodeUtil from '../../utils/vscodeUtils'; -import { runPostgresQuery } from '../runPostgresQuery'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; -import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { EOL } from "os"; +import * as path from "path"; +import { ClientConfig, QueryResult } from "pg"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import * as vscodeUtil from "../../utils/vscodeUtils"; +import { runPostgresQuery } from "../runPostgresQuery"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { checkAuthentication } from "./checkAuthentication"; +import { loadPersistedPostgresDatabase } from "./registerPostgresCommands"; -export async function executePostgresQueryInDocument(context: IActionContext): Promise { - await loadPersistedPostgresDatabase(); +export async function executePostgresQueryInDocument( + context: IActionContext +): Promise { + await loadPersistedPostgresDatabase(); - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } + let treeItem: PostgresDatabaseTreeItem; + if (ext.connectedPostgresDB) { + treeItem = ext.connectedPostgresDB; + } else { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); + const clientConfig: ClientConfig = await checkAuthentication( + context, + treeItem + ); - const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + const activeEditor: vscode.TextEditor | undefined = + vscode.window.activeTextEditor; - if (!activeEditor?.document) { - throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); - } + if (!activeEditor?.document) { + throw new Error( + localize( + "openQueryBeforeExecuting", + "Open a PostgreSQL query before executing." + ) + ); + } - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); - ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); + const query: string | undefined = activeEditor.document.getText(); + const queryResult: QueryResult = await runPostgresQuery( + clientConfig, + query + ); + ext.outputChannel.appendLine( + localize( + "executedQuery", + 'Successfully executed "{0}" query.', + queryResult.command + ) + ); - if (queryResult.rowCount) { - const fileExtension: string = path.extname(activeEditor.document.fileName); - const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); - const outputFileName: string = `${queryFileName}-output`; + if (queryResult.rowCount) { + const fileExtension: string = path.extname( + activeEditor.document.fileName + ); + const queryFileName: string = path.basename( + activeEditor.document.fileName, + fileExtension + ); + const outputFileName: string = `${queryFileName}-output`; - const fields: string[] = queryResult.fields.map(f => f.name); - let csvData: string = `${fields.join(',')}${EOL}`; + const fields: string[] = queryResult.fields.map((f) => f.name); + let csvData: string = `${fields.join(",")}${EOL}`; - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(',')}${EOL}`; - } + for (const row of queryResult.rows) { + const fieldValues: string[] = []; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + fieldValues.push(row[field]); + } + csvData += `${fieldValues.join(",")}${EOL}`; + } - await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); - } - await treeItem.refresh(context); + await vscodeUtil.showNewFile(csvData, outputFileName, ".csv"); + } + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/openPostgresFunction.ts b/Source/postgres/commands/openPostgresFunction.ts index 26103970f..4b186ed71 100644 --- a/Source/postgres/commands/openPostgresFunction.ts +++ b/Source/postgres/commands/openPostgresFunction.ts @@ -9,13 +9,20 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } +export async function openPostgresFunction( + context: IActionContext, + treeItem?: PostgresFunctionTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresFunctionTreeItem.contextValue, + } + ); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/openPostgresStoredProcedure.ts b/Source/postgres/commands/openPostgresStoredProcedure.ts index 3c98ff743..1eb8931aa 100644 --- a/Source/postgres/commands/openPostgresStoredProcedure.ts +++ b/Source/postgres/commands/openPostgresStoredProcedure.ts @@ -9,13 +9,21 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } +export async function openPostgresStoredProcedure( + context: IActionContext, + treeItem?: PostgresStoredProcedureTreeItem +): Promise { + if (!treeItem) { + treeItem = + await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresStoredProcedureTreeItem.contextValue, + } + ); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/registerPostgresCommands.ts b/Source/postgres/commands/registerPostgresCommands.ts index b861e00f7..89412a2ba 100644 --- a/Source/postgres/commands/registerPostgresCommands.ts +++ b/Source/postgres/commands/registerPostgresCommands.ts @@ -3,10 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; import { defaults } from "pg"; import { languages } from "vscode"; -import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; +import { + connectedPostgresKey, + doubleClickDebounceDelay, + postgresDefaultDatabase, + postgresLanguageId, +} from "../../constants"; import { ext } from "../../extensionVariables"; import { openUrl } from "../../utils/openUrl"; import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; @@ -28,55 +37,126 @@ import { openPostgresFunction } from "./openPostgresFunction"; import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); + ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); + ext.context.subscriptions.push( + languages.registerCodeLensProvider( + postgresLanguageId, + ext.postgresCodeLensProvider + ) + ); - void loadPersistedPostgresDatabase(); + void loadPersistedPostgresDatabase(); - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; + //update defaults.database of 'pg' + defaults.database = postgresDefaultDatabase; - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); - registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); - registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); - registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); - registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); - registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteServer", + deletePostgresServer + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.enterCredentials", + enterPostgresCredentials + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.configureFirewall", + configurePostgresFirewall + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createDatabase", + createPostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteDatabase", + deletePostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteTable", + deletePostgresTable + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.openFunction", + openPostgresFunction, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.openStoredProcedure", + openPostgresStoredProcedure, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteFunction", + deletePostgresFunction + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteStoredProcedure", + deletePostgresStoredProcedure + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.connectDatabase", + connectPostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createFunctionQuery", + createPostgresFunctionQuery + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createStoredProcedureQuery", + createPostgresStoredProcedureQuery + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.executeQuery", + executePostgresQueryInDocument + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.copyConnectionString", + copyConnectionString + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.showPasswordlessWiki", + showPasswordlessWiki + ); } export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling( + "postgreSQL.loadPersistedDatabase", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = "true"; - try { - const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); - if (persistedTreeItem) { - await connectPostgresDatabase(context, persistedTreeItem); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); + try { + const persistedTreeItemId: string | undefined = + ext.context.globalState.get(connectedPostgresKey); + if (persistedTreeItemId) { + const persistedTreeItem: + | PostgresDatabaseTreeItem + | undefined = ( + await ext.rgApi.appResourceTree.findTreeItem( + persistedTreeItemId, + context + ) + ); + if (persistedTreeItem) { + await connectPostgresDatabase( + context, + persistedTreeItem + ); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase( + undefined + ); + } + } + } + ); } export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); + await openUrl("https://aka.ms/postgresql-passwordless-wiki"); } diff --git a/Source/postgres/commands/setPostgresCredentials.ts b/Source/postgres/commands/setPostgresCredentials.ts index 8df8260f6..2807acc3c 100644 --- a/Source/postgres/commands/setPostgresCredentials.ts +++ b/Source/postgres/commands/setPostgresCredentials.ts @@ -8,25 +8,37 @@ import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } -export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; +export async function setPostgresCredentials( + username: string, + password: string, + serverId: string +): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = + ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue + ? JSON.parse(storedValue) + : []; - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); + // Remove this server from the cache if it's there + servers = servers.filter((server: IPersistedServer) => { + return server.id !== serverId; + }); - const newServer: IPersistedServer = { - id: serverId, - username - }; + const newServer: IPersistedServer = { + id: serverId, + username, + }; - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); + servers.push(newServer); + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.store( + getSecretStorageKey(serviceName, serverId), + password + ); } diff --git a/Source/postgres/getClientConfig.ts b/Source/postgres/getClientConfig.ts index bdc545945..431a95bea 100644 --- a/Source/postgres/getClientConfig.ts +++ b/Source/postgres/getClientConfig.ts @@ -8,12 +8,15 @@ import { ConnectionOptions } from "tls"; import { postgresDefaultPort } from "../constants"; import { nonNullProp } from "../utils/nonNull"; import { PostgresServerType } from "./abstract/models"; -import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; +import { + ParsedPostgresConnectionString, + addDatabaseToConnectionString, +} from "./postgresConnectionStrings"; export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; + password: ClientConfig | undefined; + azureAd: ClientConfig | undefined; + connectionString: ClientConfig | undefined; }; export type PostgresClientConfigType = keyof PostgresClientConfigs; @@ -21,82 +24,133 @@ export type PostgresClientConfigType = keyof PostgresClientConfigs; * Test if the database can be connected to using the given client config. * @throws if the client failed to connect to the database. */ -export async function testClientConfig(clientConfig: ClientConfig): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } +export async function testClientConfig( + clientConfig: ClientConfig +): Promise { + const client = new Client(clientConfig); + try { + await client.connect(); + } finally { + await client.end(); + } } -async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString(connectionString, databaseName); - } - return { connectionString: connectionString }; +async function getConnectionStringClientConfig( + parsedConnectionString: ParsedPostgresConnectionString, + databaseName: string +): Promise { + let connectionString = parsedConnectionString.connectionString; + if (!parsedConnectionString.databaseName) { + connectionString = addDatabaseToConnectionString( + connectionString, + databaseName + ); + } + return { connectionString: connectionString }; } -async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; +async function getUsernamePasswordClientConfig( + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string +): Promise { + const host = nonNullProp(parsedConnectionString, "hostName"); + const port: number = parsedConnectionString.port + ? parseInt(parsedConnectionString.port) + : parseInt(postgresDefaultPort); + const username: string | undefined = parsedConnectionString.username; + const password: string | undefined = parsedConnectionString.password; - if (!!username && !!password && !!host && !!port) { - return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; - } else { - return undefined; - } + if (!!username && !!password && !!host && !!port) { + return { + user: username, + password, + ssl: sslAzure, + host, + port, + database: databaseName, + }; + } else { + return undefined; + } } async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string, + azureAdUserId: string, + getToken: () => Promise ): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; + const host = nonNullProp(parsedConnectionString, "hostName"); + const port: number = parsedConnectionString.port + ? parseInt(parsedConnectionString.port) + : parseInt(postgresDefaultPort); + return { + user: azureAdUserId, + password: getToken, + ssl: sslAzure, + host, + port, + database: databaseName, + }; } export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + serverType: PostgresServerType, + hasSubscription: boolean, + databaseName: string, + azureUserId?: string, + getToken?: () => Promise ): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] - }; - const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { - const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); - clientConfigs.connectionString = connectionStringClientConfig; - } + const clientConfigs: PostgresClientConfigs = { + password: undefined, + azureAd: undefined, + connectionString: undefined, + }; + if (hasSubscription) { + const sslAzure: ConnectionOptions = { + // Always provide the certificate since it is accepted even when SSL is disabled + // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) + // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 + ca: + serverType === PostgresServerType.Single + ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] + : [DigiCertGlobalRootCA], + }; + const passwordClientConfig = await getUsernamePasswordClientConfig( + parsedConnectionString, + sslAzure, + databaseName + ); + if (passwordClientConfig) { + clientConfigs.password = passwordClientConfig; + } + if ( + serverType === PostgresServerType.Flexible && + !!azureUserId && + !!getToken + ) { + const azureAdClientConfig = await getAzureAdClientConfig( + parsedConnectionString, + sslAzure, + databaseName, + azureUserId, + getToken + ); + clientConfigs.azureAd = azureAdClientConfig; + } + } else { + const connectionStringClientConfig = + await getConnectionStringClientConfig( + parsedConnectionString, + databaseName + ); + clientConfigs.connectionString = connectionStringClientConfig; + } - return clientConfigs; + return clientConfigs; } // Postgres Single Server Root Cert, https://aka.ms/AA7wnvl @@ -169,4 +223,3 @@ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE-----`; - diff --git a/Source/postgres/getPostgresProcedureQueryRows.ts b/Source/postgres/getPostgresProcedureQueryRows.ts index ad791ff2e..0cecca979 100644 --- a/Source/postgres/getPostgresProcedureQueryRows.ts +++ b/Source/postgres/getPostgresProcedureQueryRows.ts @@ -9,16 +9,16 @@ import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; + schema: string; + name: string; + oid: number; + args: string; + definition: string; } function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, + // Adapted from https://aka.ms/AA83fg8 + return `select n.nspname as schema, p.proname as name, p.oid as oid, pg_get_function_arguments(p.oid) as args, @@ -33,26 +33,37 @@ function getProceduresQuery(conditions: string): string { order by name;`; } -export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { - let conditions: string; +export async function getPostgresProcedureQueryRows( + treeItem: PostgresResourcesTreeItemBase +): Promise { + let conditions: string; - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } + if (treeItem instanceof PostgresFunctionsTreeItem) { + conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') + ${ + (await treeItem.parent.parent.supportsStoredProcedures( + treeItem.clientConfig + )) + ? "and p.prokind = 'f'" + : "" + }`; + } else { + // Assume stored procedures + conditions = "and p.prokind = 'p'"; + } - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; + const query: string = getProceduresQuery(conditions); + const queryResult: QueryResult = await runPostgresQuery( + treeItem.clientConfig, + query + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } + treeItem.resourcesAndSchemas = {}; + for (const row of rows) { + treeItem.addResourcesAndSchemasEntry(row.name, row.schema); + } - return rows; + return rows; } diff --git a/Source/postgres/getTables.ts b/Source/postgres/getTables.ts index ebc7d1c75..e74d1074d 100644 --- a/Source/postgres/getTables.ts +++ b/Source/postgres/getTables.ts @@ -7,10 +7,10 @@ import { ClientConfig, QueryResult } from "pg"; import { runPostgresQuery } from "./runPostgresQuery"; export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; + schemaName: string; + name: string; + oid: string; + columnNames: string[]; } const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, @@ -23,12 +23,22 @@ const tablesQuery: string = `select schemaname, tablename, array_agg (columnname where schemaname != 'pg_catalog' AND schemaname != 'information_schema' group by schemaname, tablename;`; -export async function getTables(clientConfig: ClientConfig): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); - } - return tablesArray; +export async function getTables( + clientConfig: ClientConfig +): Promise { + const tableInfoRows: QueryResult = await runPostgresQuery( + clientConfig, + tablesQuery + ); + const tablesArray: IPostgresTable[] = []; + for (const row of tableInfoRows.rows) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + tablesArray.push({ + schemaName: row.schemaname, + name: row.tablename, + oid: row.oid, + columnNames: row.columnnames, + }); + } + return tablesArray; } diff --git a/Source/postgres/postgresConnectionStrings.ts b/Source/postgres/postgresConnectionStrings.ts index ea9ce9e2e..f1c46e6e7 100644 --- a/Source/postgres/postgresConnectionStrings.ts +++ b/Source/postgres/postgresConnectionStrings.ts @@ -8,67 +8,84 @@ import { postgresDefaultPort } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; import { nonNullProp } from "../utils/nonNull"; -export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); +export function parsePostgresConnectionString( + connectionString: string +): ParsedPostgresConnectionString { + const config: ConnectionOptions = parse(connectionString.trim()); + return new ParsedPostgresConnectionString(connectionString, config); } -export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); +export function addDatabaseToConnectionString( + connectionString: string, + databaseName: string +): string { + const url = new URL(connectionString); + url.pathname = encodeURIComponent(databaseName); + return url.toString(); } -export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function createPostgresConnectionString( + hostName: string, + port: string = postgresDefaultPort, + username?: string | undefined, + password?: string | undefined, + databaseName?: string | undefined +): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + connectionString += `${encodedUsername}:${encodedPassword}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } -export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function copyPostgresConnectionString( + hostName: string, + port: string = postgresDefaultPort, + username?: string | undefined, + password?: string | undefined, + databaseName?: string | undefined +): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; + connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; + public readonly hostName: string; + public username: string | undefined; + public password: string | undefined; + public readonly port: string; - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, 'host'); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } + constructor(connectionString: string, config: ConnectionOptions) { + super(connectionString, config.database ? config.database : undefined); + this.hostName = nonNullProp(config, "host"); + this.port = config.port ? config.port : `${postgresDefaultPort}`; + this.username = config.user; + this.password = config.password; + } } diff --git a/Source/postgres/postgresConstants.ts b/Source/postgres/postgresConstants.ts index 9bcf15144..f94f58a25 100644 --- a/Source/postgres/postgresConstants.ts +++ b/Source/postgres/postgresConstants.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const invalidCredentialsErrorType: string = '28P01'; -export const firewallNotConfiguredErrorType: string = '28000'; -export const timeoutErrorType = 'ETIMEDOUT'; +export const invalidCredentialsErrorType: string = "28P01"; +export const firewallNotConfiguredErrorType: string = "28000"; +export const timeoutErrorType = "ETIMEDOUT"; diff --git a/Source/postgres/runPostgresQuery.ts b/Source/postgres/runPostgresQuery.ts index b7d325364..ce2a67c7b 100644 --- a/Source/postgres/runPostgresQuery.ts +++ b/Source/postgres/runPostgresQuery.ts @@ -5,15 +5,18 @@ import { Client, ClientConfig, QueryResult } from "pg"; -export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } +export async function runPostgresQuery( + clientConfig: ClientConfig, + query: string +): Promise { + const client: Client = new Client(clientConfig); + try { + await client.connect(); + return await client.query(query); + } finally { + await client.end(); + } } export function wrapArgInQuotes(input: string): string { - return `"${input}"`; + return `"${input}"`; } diff --git a/Source/postgres/services/PostgresCodeLensProvider.ts b/Source/postgres/services/PostgresCodeLensProvider.ts index 5d075eb3c..d0d6bfe39 100644 --- a/Source/postgres/services/PostgresCodeLensProvider.ts +++ b/Source/postgres/services/PostgresCodeLensProvider.ts @@ -3,64 +3,88 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { + CodeLens, + CodeLensProvider, + Event, + EventEmitter, + Position, + ProviderResult, + Range, +} from "vscode"; import { localize } from "../../utils/localize"; export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: EventEmitter = new EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(): ProviderResult { + return callWithTelemetryAndErrorHandling( + "postgreSQL.provideCodeLenses", + (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: CodeLens[] = []; - let title: string; - if (!isInitialized) { - title = localize('initializing', 'Initializing...'); - } else if (isConnected) { - title = localize('connectedToDatabase', 'Connected to "{0}"', database); - } else { - title = localize('connectToDatabase', 'Connect to a database'); - } + let title: string; + if (!isInitialized) { + title = localize("initializing", "Initializing..."); + } else if (isConnected) { + title = localize( + "connectedToDatabase", + 'Connected to "{0}"', + database + ); + } else { + title = localize( + "connectToDatabase", + "Connect to a database" + ); + } - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && 'postgreSQL.connectDatabase' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title, + command: isInitialized && "postgreSQL.connectDatabase", + }, + range: new Range(new Position(0, 0), new Position(0, 0)), + }); - if (isConnected) { - lenses.push({ - command: { - title: 'Execute Query', - command: 'postgreSQL.executeQuery' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - } + if (isConnected) { + lenses.push({ + command: { + title: "Execute Query", + command: "postgreSQL.executeQuery", + }, + range: new Range( + new Position(0, 0), + new Position(0, 0) + ), + }); + } - return lenses; - }); - } + return lenses; + } + ); + } } diff --git a/Source/postgres/showPostgresQuery.ts b/Source/postgres/showPostgresQuery.ts index 7d6e2aa1d..4d1b277b4 100644 --- a/Source/postgres/showPostgresQuery.ts +++ b/Source/postgres/showPostgresQuery.ts @@ -3,12 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { postgresBaseFileName, postgresFileExtension } from '../constants'; -import * as vscodeUtil from '../utils/vscodeUtils'; +import { postgresBaseFileName, postgresFileExtension } from "../constants"; +import * as vscodeUtil from "../utils/vscodeUtils"; import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; -export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); +export async function showPostgresQuery( + treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem +): Promise { + const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; + await vscodeUtil.showNewFile( + treeItem.definition, + fileName, + postgresFileExtension + ); } diff --git a/Source/postgres/tree/ClientConfigFactory.ts b/Source/postgres/tree/ClientConfigFactory.ts index 271f5b92f..67a00710c 100644 --- a/Source/postgres/tree/ClientConfigFactory.ts +++ b/Source/postgres/tree/ClientConfigFactory.ts @@ -3,84 +3,123 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + parseError, +} from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; +import { + getAzureAdUserSession, + getTokenFunction, +} from "../../azureAccountUtils"; import { localize } from "../../utils/localize"; -import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; +import { + PostgresClientConfigType, + getClientConfigs, + testClientConfig, +} from "../getClientConfig"; +import { + firewallNotConfiguredErrorType, + invalidCredentialsErrorType, + timeoutErrorType, +} from "../postgresConstants"; import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; +export const postgresResourceType = + "https://ossrdbms-aad.database.windows.net/"; /** * Creates an object that can be used to execute a postgres query with connection test and telemetry. */ export class PostgresClientConfigFactory { - public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ - type: "azureAd" | "password" | "connectionString", - clientConfig: ClientConfig - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); + public static async getClientConfigFromNode( + treeItem: PostgresServerTreeItem, + databaseName: string + ): Promise<{ + type: "azureAd" | "password" | "connectionString"; + clientConfig: ClientConfig; + }> { + const parsedConnectionString = await treeItem.getFullConnectionString(); + const azureUserSession = await getAzureAdUserSession(); - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); + let hasSubscription: boolean = false; + let tokenFunction: (() => Promise) | undefined = undefined; + try { + const subscription = treeItem.subscription; + hasSubscription = true; + tokenFunction = getTokenFunction( + subscription.credentials, + postgresResourceType + ); + } catch (error) { + hasSubscription = false; + } + const clientConfigs = await getClientConfigs( + parsedConnectionString, + treeItem.serverType, + hasSubscription, + databaseName, + azureUserSession?.userId, + tokenFunction + ); - const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; + const clientConfigTypeOrder: PostgresClientConfigType[] = [ + "azureAd", + "password", + "connectionString", + ]; - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } + for (const clientConfigType of clientConfigTypeOrder) { + const clientConfig: ClientConfig | undefined = + clientConfigs[clientConfigType]; + if (!clientConfig) { + continue; + } - try { - await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = clientConfigType; - await testClientConfig(clientConfig); - }); - return { - type: clientConfigType, - clientConfig - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), - code: firewallNotConfiguredErrorType - }; - } else { - throw error; - } - } - } + try { + await callWithTelemetryAndErrorHandling( + "postgreSQL.testClientConfig", + async (context) => { + context.errorHandling.rethrow = true; + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.clientConfigType = + clientConfigType; + await testClientConfig(clientConfig); + } + ); + return { + type: clientConfigType, + clientConfig, + }; + } catch (error) { + const parsedError = parseError(error); + if (parsedError.errorType === invalidCredentialsErrorType) { + // If the client config failed with invalid credential error, skip and try the next available one. + } else if ( + parsedError.errorType === firewallNotConfiguredErrorType || + parsedError.errorType === timeoutErrorType + ) { + // The time out error are common when the firewall rules doesn't grant access from the current IP address. + // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. + throw { + message: localize( + "mustConfigureFirewall", + "Must configure firewall from Azure Portal to grant access." + ), + code: firewallNotConfiguredErrorType, + }; + } else { + throw error; + } + } + } - throw { - message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), - code: invalidCredentialsErrorType - }; - } + throw { + message: localize( + "mustEnterCredentials", + "Must enter credentials to connect to server." + ), + code: invalidCredentialsErrorType, + }; + } } diff --git a/Source/postgres/tree/PostgresColumnTreeItem.ts b/Source/postgres/tree/PostgresColumnTreeItem.ts index d284c8122..aedfa46f2 100644 --- a/Source/postgres/tree/PostgresColumnTreeItem.ts +++ b/Source/postgres/tree/PostgresColumnTreeItem.ts @@ -3,31 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; +import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; + public static contextValue: string = "postgresColumn"; + public readonly contextValue: string = PostgresColumnTreeItem.contextValue; + public readonly columnName: string; + public readonly parent: PostgresTableTreeItem; - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } + constructor(parent: PostgresTableTreeItem, columnName: string) { + super(parent); + this.columnName = columnName; + } - public get id(): string { - return this.columnName; - } + public get id(): string { + return this.columnName; + } - public get label(): string { - return this.columnName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('split-horizontal'); - } + public get label(): string { + return this.columnName; + } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("split-horizontal"); + } } diff --git a/Source/postgres/tree/PostgresDatabaseTreeItem.ts b/Source/postgres/tree/PostgresDatabaseTreeItem.ts index 05f7a4412..e9463d0bc 100644 --- a/Source/postgres/tree/PostgresDatabaseTreeItem.ts +++ b/Source/postgres/tree/PostgresDatabaseTreeItem.ts @@ -4,112 +4,178 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line import/no-internal-modules -import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { ThemeIcon } from 'vscode'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresServerTreeItem } from './PostgresServerTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import { + AzExtParentTreeItem, + AzExtTreeItem, + createContextValue, + GenericTreeItem, + IActionContext, + IParsedError, + parseError, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { ThemeIcon } from "vscode"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { + firewallNotConfiguredErrorType, + invalidCredentialsErrorType, +} from "../postgresConstants"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresClientConfigFactory } from "./ClientConfigFactory"; +import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; +import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; +import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; + public static contextValue: string = "postgresDatabase"; + public contextValue: string = PostgresDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Resource Type"; + public readonly databaseName: string; + public readonly parent: PostgresServerTreeItem; + public autoSelectInTreeItemPicker: boolean = true; + public isShowingPasswordWarning: boolean; - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } + constructor(parent: PostgresServerTreeItem, databaseName: string) { + super(parent); + this.databaseName = databaseName; + this.isShowingPasswordWarning = false; + } - public get label(): string { - return this.databaseName; - } + public get label(): string { + return this.databaseName; + } - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; - } + public get description(): string { + return ext.connectedPostgresDB?.fullId === this.fullId + ? localize("connected", "Connected") + : ""; + } - public get id(): string { - return this.databaseName; - } + public get id(): string { + return this.databaseName; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('database'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("database"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresFirewall', - label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.configureFirewall' - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: "postgresFirewall", + label: localize( + "configureFirewall", + 'Configure firewall to connect to "{0}"...', + this.parent.label + ), + commandId: "postgreSQL.configureFirewall", + }); + firewallTreeItem.commandArgs = [this.parent]; + return [firewallTreeItem]; + } - try { - const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig) - ]; + try { + const { type, clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this.parent, + this.databaseName + ); + if (type === "password") { + void this.showPasswordWarning(context); + } + const children: AzExtTreeItem[] = [ + new PostgresFunctionsTreeItem(this, clientConfig), + new PostgresTablesTreeItem(this, clientConfig), + ]; - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); - } + if (await this.parent.supportsStoredProcedures(clientConfig)) { + children.push( + new PostgresStoredProceduresTreeItem(this, clientConfig) + ); + } - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); + return children; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresCredentials', - label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.enterCredentials' - }); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - return []; - } else { - throw error; - } - } - } + if ( + this.parent.azureName && + parsedError.errorType === invalidCredentialsErrorType + ) { + void context.ui.showWarningMessage( + localize( + "couldNotConnect", + 'Could not connect to "{0}": {1}', + this.parent.label, + parsedError.message + ), + { stepName: "loadPostgresDatabases" } + ); + const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem( + this, + { + contextValue: "postgresCredentials", + label: localize( + "enterCredentials", + 'Enter server credentials to connect to "{0}"...', + this.parent.label + ), + commandId: "postgreSQL.enterCredentials", + } + ); + credentialsTreeItem.commandArgs = [this.parent]; + return [credentialsTreeItem]; + } else if ( + this.parent.azureName && + parsedError.errorType === firewallNotConfiguredErrorType + ) { + void context.ui.showWarningMessage( + localize( + "couldNotConnect", + 'Could not connect to "{0}": {1}', + this.parent.label, + parsedError.message + ), + { stepName: "loadPostgresDatabases" } + ); + return []; + } else { + throw error; + } + } + } - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); - } + public async deleteTreeItemImpl(): Promise { + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this.parent, + this.databaseName + ); + await runPostgresQuery( + clientConfig, + `Drop Database ${wrapArgInQuotes(this.databaseName)};` + ); + } - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); - await this.refresh(context); - } + private async showPasswordWarning(context: IActionContext): Promise { + if (this.isShowingPasswordWarning) { + return; + } + this.isShowingPasswordWarning = true; + this.contextValue = createContextValue([ + PostgresDatabaseTreeItem.contextValue, + "usesPassword", + ]); + await this.refresh(context); + } } diff --git a/Source/postgres/tree/PostgresFunctionTreeItem.ts b/Source/postgres/tree/PostgresFunctionTreeItem.ts index 0a26bf3f9..d7bc46a16 100644 --- a/Source/postgres/tree/PostgresFunctionTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionTreeItem.ts @@ -10,39 +10,49 @@ import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresFunction'; - public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = "postgresFunction"; + public readonly contextValue: string = + PostgresFunctionTreeItem.contextValue; + public readonly parent: PostgresFunctionsTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openFunction'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor( + parent: PostgresFunctionsTreeItem, + row: IPostgresProceduresQueryRow, + isDuplicate: boolean + ) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = "postgreSQL.openFunction"; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("symbol-function"); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${ + this.args + });` + ); + } } diff --git a/Source/postgres/tree/PostgresFunctionsTreeItem.ts b/Source/postgres/tree/PostgresFunctionsTreeItem.ts index 7d3904e83..8f373ab95 100644 --- a/Source/postgres/tree/PostgresFunctionsTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionsTreeItem.ts @@ -4,43 +4,51 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { ClientConfig } from "pg"; +import { ThemeIcon } from "vscode"; +import { + getPostgresProcedureQueryRows, + IPostgresProceduresQueryRow, +} from "../getPostgresProcedureQueryRows"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; +import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresFunctions'; - public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; - public readonly label: string = 'Functions'; - public readonly childTypeLabel: string = 'Function'; - public suppressMaskLabel = true; + public static contextValue: string = "postgresFunctions"; + public readonly contextValue: string = + PostgresFunctionsTreeItem.contextValue; + public readonly label: string = "Functions"; + public readonly childTypeLabel: string = "Function"; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("symbol-function"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = + await getPostgresProcedureQueryRows(this); + return rows.map( + (row) => + new PostgresFunctionTreeItem( + this, + row, + this.isDuplicateResource(row.name) + ) + ); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresFunctionTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts index b93cc9450..40e4d07c5 100644 --- a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts +++ b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts @@ -9,19 +9,19 @@ import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; // Base class for Postgres tree items whose children are individual resources export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas + public parent: PostgresDatabaseTreeItem; + public clientConfig: ClientConfig; + public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } + public addResourcesAndSchemasEntry(name: string, schema: string): void { + if (this.resourcesAndSchemas[name]) { + this.resourcesAndSchemas[name].push(schema); + } else { + this.resourcesAndSchemas[name] = [schema]; + } + } - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } + public isDuplicateResource(name: string): boolean { + return this.resourcesAndSchemas[name].length > 1; + } } diff --git a/Source/postgres/tree/PostgresServerTreeItem.ts b/Source/postgres/tree/PostgresServerTreeItem.ts index 20e7dbe76..1ffc11403 100644 --- a/Source/postgres/tree/PostgresServerTreeItem.ts +++ b/Source/postgres/tree/PostgresServerTreeItem.ts @@ -3,250 +3,383 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from '@azure/arm-postgresql'; -import * as FlexibleModels from '@azure/arm-postgresql-flexible'; -import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import { ClientConfig } from 'pg'; -import { SemVer, coerce, gte } from 'semver'; -import * as vscode from 'vscode'; -import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { isIpInRanges } from '../../utils/getIp'; -import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; -import { getPublicIp } from '../commands/configurePostgresFirewall'; -import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import * as SingleModels from "@azure/arm-postgresql"; +import * as FlexibleModels from "@azure/arm-postgresql-flexible"; +import { + getResourceGroupFromId, + parseAzureResourceId, + uiUtils, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + IActionContext, + ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import { ClientConfig } from "pg"; +import { SemVer, coerce, gte } from "semver"; +import * as vscode from "vscode"; +import { + getThemeAgnosticIconPath, + postgresDefaultDatabase, +} from "../../constants"; +import { ext } from "../../extensionVariables"; +import { isIpInRanges } from "../../utils/getIp"; +import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../abstract/AbstractPostgresClient"; +import { PostgresAbstractServer, PostgresServerType } from "../abstract/models"; +import { getPublicIp } from "../commands/configurePostgresFirewall"; +import { ParsedPostgresConnectionString } from "../postgresConnectionStrings"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresClientConfigFactory } from "./ClientConfigFactory"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; +import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; +import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; +import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; +import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; - } - this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('PostgresServer.svg'); - } - - public get label(): string { - return this.azureName ? this.azureName : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); - dbNames = listOfDatabases.map(db => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map(db => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - 'invalidPostgresServer', - dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, - dbName => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); - } - const getChildrenTask: Promise = this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createPostgresDatabase', - validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) - }); - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, '11.0.0'); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); - - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); - } - - public async getFullConnectionString(): Promise { - - if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { - const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp(this, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); - const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } + public static contextValue: string = "postgresServer"; + public static serviceName: string = + "ms-azuretools.vscode-azuredatabases.postgresPasswords"; + public readonly contextValue: string = PostgresServerTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly serverType: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + constructor( + parent: AzExtParentTreeItem, + connectionString: ParsedPostgresConnectionString, + server?: PostgresAbstractServer + ) { + super(parent); + this.partialConnectionString = connectionString; + if (server) { + this.azureId = server?.id; + this.serverVersion = server?.version; + this.resourceGroup = getResourceGroupFromId(this.fullId); + this.azureName = server?.name; + this.serverType = parseAzureResourceId(this.fullId) + .provider.toLowerCase() + .includes("flexible") + ? PostgresServerType.Flexible + : PostgresServerType.Single; + } + this.valuesToMask.push( + connectionString.accountId, + connectionString.connectionString, + connectionString.fullId, + connectionString.hostName, + connectionString.port + ); + if (connectionString.databaseName) { + this.valuesToMask.push(connectionString.databaseName); + } + } + + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("PostgresServer.svg"); + } + + public get label(): string { + return this.azureName + ? this.azureName + : this.partialConnectionString.fullId; + } + + public get id(): string { + if (this.azureId) { + return this.azureId; + } + return this.partialConnectionString.fullId; + } + + public get description(): string | undefined { + switch (this.serverType) { + case PostgresServerType.Flexible: + return "PostgreSQL Flexible"; + case PostgresServerType.Single: + return "PostgreSQL Single"; + default: + return "PostgreSQL"; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + context.telemetry.properties.serverType = this.serverType; + let dbNames: (string | undefined)[]; + if (this.azureName) { + const client: AbstractPostgresClient = + await createAbstractPostgresClient(this.serverType, [ + context, + this.subscription, + ]); + const listOfDatabases: ( + | SingleModels.Database + | FlexibleModels.Database + )[] = await uiUtils.listAllIterator( + client.databases.listByServer( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ) + ); + dbNames = listOfDatabases.map((db) => db.name); + } else if (this.partialConnectionString.databaseName) { + dbNames = [this.partialConnectionString.databaseName]; + } else { + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this, + postgresDefaultDatabase + ); + const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; + const queryResult = await runPostgresQuery(clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + dbNames = queryResult.rows.map((db) => db?.datname); + } + + return this.createTreeItemsWithErrorHandling( + dbNames, + "invalidPostgresServer", + (dbName) => + dbName && !["azure_maintenance", "azure_sys"].includes(dbName) + ? new PostgresDatabaseTreeItem(this, dbName) + : undefined, + (dbName) => dbName + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case PostgresDatabaseTreeItem.contextValue: + case PostgresTablesTreeItem.contextValue: + case PostgresTableTreeItem.contextValue: + case PostgresFunctionsTreeItem.contextValue: + case PostgresFunctionTreeItem.contextValue: + case PostgresStoredProceduresTreeItem.contextValue: + case PostgresStoredProcedureTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + if (this.partialConnectionString.databaseName) { + throw new Error( + localize( + "noPermissionToCreateDatabase", + `This attached account does not have permissions to create a database.` + ) + ); + } + const getChildrenTask: Promise = + this.getCachedChildren(context); + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: "createPostgresDatabase", + validateInput: (name: string) => + validateDatabaseName(name, getChildrenTask), + }); + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this, + databaseName + ); + context.showCreatingTreeItem(databaseName); + await runPostgresQuery( + clientConfig, + `Create Database ${wrapArgInQuotes(databaseName)};` + ); + return new PostgresDatabaseTreeItem(this, databaseName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const client = await createAbstractPostgresClient(this.serverType, [ + context, + this.subscription, + ]); + const deletingMessage: string = `Deleting server "${this.label}"...`; + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: deletingMessage, + }, + async () => { + await client.servers.beginDeleteAndWait( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ); + await this.deletePostgresCredentials(); + + const deleteMessage: string = localize( + "deleteServerMsg", + 'Successfully deleted server "{0}".', + this.label + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + } + ); + } + + public setCredentials(username: string, password: string): void { + this.partialConnectionString.username = username; + this.partialConnectionString.password = password; + } + + public async supportsStoredProcedures( + clientConfig: ClientConfig + ): Promise { + // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer + if (!this.serverVersion) { + const result = await runPostgresQuery( + clientConfig, + `SHOW server_version;` + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + this.serverVersion = result.rows[0].server_version; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + const version: SemVer | null = coerce(this.serverVersion); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call + return gte(version, "11.0.0"); + } + + public async deletePostgresCredentials(): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = + ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue + ? JSON.parse(storedValue) + : []; + + // Remove this server from the cache + servers = servers.filter((server: IPersistedServer) => { + return server.id !== this.id; + }); + + await ext.context.globalState.update( + serviceName, + JSON.stringify(servers) + ); + await ext.secretStorage.delete( + getSecretStorageKey(serviceName, this.id) + ); + } + + public async getFullConnectionString(): Promise { + if ( + this.azureId && + !( + this.partialConnectionString.username && + this.partialConnectionString.password + ) + ) { + const storedValue: string | undefined = ext.context.globalState.get( + PostgresServerTreeItem.serviceName + ); + if (storedValue) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const servers: IPersistedServer[] = JSON.parse(storedValue); + for (const server of servers) { + if (server.id === this.id) { + this.partialConnectionString.username = server.username; + // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials + this.partialConnectionString.password = + (await ext.secretStorage.get( + getSecretStorageKey( + PostgresServerTreeItem.serviceName, + this.id + ) + )) || undefined; + break; + } + } + } + } + return this.partialConnectionString; + } + + /** + * @returns true if we believe the firewall allows the current IP to connect to database server. + */ + public async isFirewallRuleSet(context: IActionContext): Promise { + try { + const serverType: PostgresServerType = nonNullProp( + this, + "serverType" + ); + const client: AbstractPostgresClient = + await createAbstractPostgresClient(serverType, [ + context, + this.subscription, + ]); + const results: SingleModels.FirewallRule[] = + await uiUtils.listAllIterator( + client.firewallRules.listByServer( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ) + ); + const publicIp: string = await getPublicIp(context); + return isIpInRanges(publicIp, results); + } catch (error) { + // We cannot get the firewall rules from attached databases because we cannot get the subscription object. + // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. + return true; + } + } } -async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { - if (!name) { - return localize('NameCannotBeEmpty', 'Name cannot be empty.'); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize('NameExists', 'Database "{0}" already exists.', name); - } - return undefined; +async function validateDatabaseName( + name: string, + getChildrenTask: Promise +): Promise { + if (!name) { + return localize("NameCannotBeEmpty", "Name cannot be empty."); + } + const currDatabaseList = await getChildrenTask; + const currDatabaseNames: string[] = []; + for (const db of currDatabaseList) { + if (db instanceof PostgresDatabaseTreeItem) { + currDatabaseNames.push(db.databaseName); + } + } + if (currDatabaseNames.includes(name)) { + return localize("NameExists", 'Database "{0}" already exists.', name); + } + return undefined; } diff --git a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts index 503d0ae74..1c903d9e2 100644 --- a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts @@ -10,39 +10,47 @@ import { runPostgresQuery } from "../runPostgresQuery"; import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresStoredProcedure'; - public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = "postgresStoredProcedure"; + public readonly contextValue: string = + PostgresStoredProcedureTreeItem.contextValue; + public readonly parent: PostgresStoredProceduresTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openStoredProcedure'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor( + parent: PostgresStoredProceduresTreeItem, + row: IPostgresProceduresQueryRow, + isDuplicate: boolean + ) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = "postgreSQL.openStoredProcedure"; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("server-process"); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});` + ); + } } diff --git a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts index 1c516e00f..9525856f6 100644 --- a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts @@ -4,43 +4,53 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; +import { ClientConfig } from "pg"; +import { ThemeIcon } from "vscode"; +import { + getPostgresProcedureQueryRows, + IPostgresProceduresQueryRow, +} from "../getPostgresProcedureQueryRows"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; +import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresStoredProcedures'; - public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = 'Stored Procedures'; - public readonly childTypeLabel: string = 'Stored Procedure'; - public suppressMaskLabel = true; + public static contextValue: string = "postgresStoredProcedures"; + public readonly contextValue: string = + PostgresStoredProceduresTreeItem.contextValue; + public readonly label: string = "Stored Procedures"; + public readonly childTypeLabel: string = "Stored Procedure"; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("server-process"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } + public async loadMoreChildrenImpl(): Promise< + PostgresStoredProcedureTreeItem[] + > { + const rows: IPostgresProceduresQueryRow[] = + await getPostgresProcedureQueryRows(this); + return rows.map( + (row) => + new PostgresStoredProcedureTreeItem( + this, + row, + this.isDuplicateResource(row.name) + ) + ); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresStoredProcedureTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresTableTreeItem.ts b/Source/postgres/tree/PostgresTableTreeItem.ts index ef5d87c2c..fb844038b 100644 --- a/Source/postgres/tree/PostgresTableTreeItem.ts +++ b/Source/postgres/tree/PostgresTableTreeItem.ts @@ -3,54 +3,68 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IPostgresTable } from '../getTables'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import { + AzExtParentTreeItem, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IPostgresTable } from "../getTables"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresColumnTreeItem } from "./PostgresColumnTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; + public static contextValue: string = "postgresTable"; + public readonly contextValue: string = PostgresTableTreeItem.contextValue; + public readonly table: IPostgresTable; + public readonly parent: PostgresTablesTreeItem; - private _isDuplicate: boolean; + private _isDuplicate: boolean; - constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } + constructor( + parent: PostgresTablesTreeItem, + table: IPostgresTable, + isDuplicate: boolean + ) { + super(parent); + this.table = table; + this._isDuplicate = isDuplicate; + } - public get id(): string { - return String(this.table.oid); - } + public get id(): string { + return String(this.table.oid); + } - public get label(): string { - return this.table.name; - } + public get label(): string { + return this.table.name; + } - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } + public get description(): string | undefined { + return this._isDuplicate ? this.table.schemaName : undefined; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('window'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("window"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); - } + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return this.table.columnNames.map( + (columnName) => new PostgresColumnTreeItem(this, columnName) + ); + } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `Drop Table ${this.table.schemaName}.${wrapArgInQuotes( + this.table.name + )};` + ); + } } diff --git a/Source/postgres/tree/PostgresTablesTreeItem.ts b/Source/postgres/tree/PostgresTablesTreeItem.ts index c18c065db..4c15ef812 100644 --- a/Source/postgres/tree/PostgresTablesTreeItem.ts +++ b/Source/postgres/tree/PostgresTablesTreeItem.ts @@ -5,47 +5,54 @@ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { ThemeIcon } from 'vscode'; +import { ThemeIcon } from "vscode"; import { getTables, IPostgresTable } from "../getTables"; import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = 'Tables'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); - } - return tables.map(table => new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } + public static contextValue: string = "postgresTables"; + public readonly contextValue: string = PostgresTablesTreeItem.contextValue; + public readonly childTypeLabel: string = "Table"; + public readonly label: string = "Tables"; + public suppressMaskLabel = true; + + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } + + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("window"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const tables: IPostgresTable[] = await getTables(this.clientConfig); + this.resourcesAndSchemas = {}; + for (const table of tables) { + this.addResourcesAndSchemasEntry( + table.name.trim(), + table.schemaName + ); + } + return tables.map( + (table) => + new PostgresTableTreeItem( + this, + table, + this.isDuplicateResource(table.name.trim()) + ) + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresTableTreeItem.contextValue; + } } diff --git a/Source/resolver/AppResolver.ts b/Source/resolver/AppResolver.ts index 0f75cdf29..7d20a4832 100644 --- a/Source/resolver/AppResolver.ts +++ b/Source/resolver/AppResolver.ts @@ -4,8 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; -import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, + ISubscriptionContext, + nonNullProp, + nonNullValue, +} from "@microsoft/vscode-azext-utils"; +import { + AppResource, + AppResourceResolver, +} from "@microsoft/vscode-azext-utils/hostapi"; import { tryGetExperience } from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; import { ext } from "../extensionVariables"; @@ -13,59 +24,111 @@ import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresAbstractServer } from "../postgres/abstract/models"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; +import { + createCosmosDBClient, + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../utils/azureClients"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; const resourceTypes = [ - 'microsoft.documentdb/databaseaccounts', - 'microsoft.dbforpostgresql/servers', - 'microsoft.dbforpostgresql/flexibleservers' + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers", ]; export class DatabaseResolver implements AppResourceResolver { - public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { - return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); - try { - const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); - const name = nonNullProp(resource, 'name'); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; + public async resolveResource( + subContext: ISubscriptionContext, + resource: AppResource + ): Promise { + return await callWithTelemetryAndErrorHandling( + "resolveResource", + async (context: IActionContext) => { + const subNode: AzExtParentTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + `/subscriptions/${subContext.subscriptionId}`, + context + ); + try { + const resourceGroupName = getResourceGroupFromId( + nonNullProp(resource, "id") + ); + const name = nonNullProp(resource, "name"); + let postgresServer: PostgresAbstractServer; + let dbChild: AzExtTreeItem; - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ ...context, ...subContext }); - const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); - const experience = tryGetExperience(databaseAccount); + switch (resource.type.toLowerCase()) { + case resourceTypes[0]: + const client = await createCosmosDBClient({ + ...context, + ...subContext, + }); + const databaseAccount = + await client.databaseAccounts.get( + resourceGroupName, + name + ); + dbChild = + await SubscriptionTreeItem.initCosmosDBChild( + client, + databaseAccount, + nonNullValue(subNode) + ); + const experience = + tryGetExperience(databaseAccount); - return experience?.api === 'MongoDB' ? - new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : - new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? - await createPostgreSQLClient({ ...context, ...subContext }) : - await createPostgreSQLFlexibleClient({ ...context, ...subContext }); + return experience?.api === "MongoDB" + ? new ResolvedMongoAccountResource( + dbChild as MongoAccountTreeItem, + resource + ) + : new ResolvedDocDBAccountResource( + dbChild as DocDBAccountTreeItem, + resource + ); + case resourceTypes[1]: + case resourceTypes[2]: + const postgresClient = + resource.type.toLowerCase() === resourceTypes[1] + ? await createPostgreSQLClient({ + ...context, + ...subContext, + }) + : await createPostgreSQLFlexibleClient({ + ...context, + ...subContext, + }); - postgresServer = await postgresClient.servers.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); + postgresServer = await postgresClient.servers.get( + resourceGroupName, + name + ); + dbChild = + await SubscriptionTreeItem.initPostgresChild( + postgresServer, + nonNullValue(subNode) + ); - return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - }); - } + return new ResolvedPostgresServerResource( + dbChild as PostgresServerTreeItem, + resource + ); + default: + return null; + } + } catch (e) { + console.error({ ...context, ...subContext }); + throw e; + } + } + ); + } - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } + public matchesResource(resource: AppResource): boolean { + return resourceTypes.includes(resource.type.toLowerCase()); + } } diff --git a/Source/resolver/DatabaseWorkspaceProvider.ts b/Source/resolver/DatabaseWorkspaceProvider.ts index 14e50d643..d1f462a36 100644 --- a/Source/resolver/DatabaseWorkspaceProvider.ts +++ b/Source/resolver/DatabaseWorkspaceProvider.ts @@ -3,31 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; import { Disposable } from "vscode"; import { ext } from "../extensionVariables"; import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; - export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise { - - return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - }); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } + public disposables: Disposable[] = []; + + constructor(parent: AzExtParentTreeItem) { + ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); + } + + public async provideResources(): Promise< + AzExtTreeItem[] | null | undefined + > { + return await callWithTelemetryAndErrorHandling( + "AzureAccountTreeItemWithProjects.provideResources", + async (_context: IActionContext) => { + return [ext.attachedAccountsNode]; + } + ); + } + private _projectDisposables: Disposable[] = []; + + public dispose(): void { + Disposable.from(...this._projectDisposables).dispose(); + } } - diff --git a/Source/resolver/ResolvedDatabaseAccountResource.ts b/Source/resolver/ResolvedDatabaseAccountResource.ts index 0222dded7..41eda32be 100644 --- a/Source/resolver/ResolvedDatabaseAccountResource.ts +++ b/Source/resolver/ResolvedDatabaseAccountResource.ts @@ -3,55 +3,78 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AzExtTreeItem, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue) - this.maskedValuestoAdd.push(...ti.valuesToMask); - } +export class ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public id: string; + public contextValuesToAdd: string[] = []; + public description: string | undefined; + + // private _databaseTreeItem: AzExtParentTreeItem; + iconPath: TreeItemIconPath | undefined; + label: string; + + readonly childTypeLabel: string; + + loadMoreChildrenImpl?( + clearCache: boolean, + context: IActionContext + ): Promise; + createChildImpl?(context: ICreateChildImplContext): Promise; + hasMoreChildrenImpl?(): boolean; + compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; + + pickTreeItemImpl?( + expectedContextValues: (string | RegExp)[], + context: IActionContext + ): AzExtTreeItem | undefined | Promise; + deleteTreeItemImpl?(context: IActionContext): Promise; + refreshImpl?(context: IActionContext): Promise; + isAncestorOfImpl?(contextValue: string): boolean; + + connectionString: string; + maskedValuestoAdd: string[] = []; + + public constructor( + ti: + | DocDBAccountTreeItemBase + | MongoAccountTreeItem + | PostgresServerTreeItem, + resource: AppResource + ) { + this.id = ti.id ?? resource.id; + // PostgresServerTreeItem require on a property on the server so wait to do this + this.description = + ti instanceof PostgresServerTreeItem ? undefined : ti.description; + this.iconPath = ti.iconPath; + this.label = ti.label; + this.childTypeLabel = ti.childTypeLabel; + + this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; + this.createChildImpl = ti.createChildImpl; + this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; + this.compareChildrenImpl = ti.compareChildrenImpl; + + this.pickTreeItemImpl = ti.pickTreeItemImpl; + this.deleteTreeItemImpl = ti.deleteTreeItemImpl; + this.refreshImpl = ti.refreshImpl; + this.isAncestorOfImpl = ti.isAncestorOfImpl; + + this.contextValuesToAdd.push(ti.contextValue); + this.maskedValuestoAdd.push(...ti.valuesToMask); + } } diff --git a/Source/resolver/ResolvedDocDBAccountResource.ts b/Source/resolver/ResolvedDocDBAccountResource.ts index cf1bfc4bc..02f17f6e3 100644 --- a/Source/resolver/ResolvedDocDBAccountResource.ts +++ b/Source/resolver/ResolvedDocDBAccountResource.ts @@ -1,32 +1,45 @@ - - /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + CosmosClient, + DatabaseDefinition, + FeedOptions, + QueryIterator, + Resource, +} from "@azure/cosmos"; import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } +export class ResolvedDocDBAccountResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public root: IDocDBTreeRoot; + + initChild: (resource: Resource) => AzExtTreeItem; + isServerless?: boolean; + getIterator?: ( + client: CosmosClient, + feedOptions: FeedOptions + ) => QueryIterator; + + public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { + super(ti, resource); + + this.connectionString = ti.connectionString; + this.root = ti.root; + + this.isServerless = ti.isServerless; + this.getIterator = ti.getIterator; + this.initChild = ti.initChild; + } } diff --git a/Source/resolver/ResolvedMongoAccountResource.ts b/Source/resolver/ResolvedMongoAccountResource.ts index 4f45486ef..80636b5e5 100644 --- a/Source/resolver/ResolvedMongoAccountResource.ts +++ b/Source/resolver/ResolvedMongoAccountResource.ts @@ -3,18 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - root: IMongoTreeRoot; +export class ResolvedMongoAccountResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + root: IMongoTreeRoot; - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); + public constructor(ti: MongoAccountTreeItem, resource: AppResource) { + super(ti, resource); - this.connectionString = ti.connectionString; - this.root = ti.root; - } + this.connectionString = ti.connectionString; + this.root = ti.root; + } } diff --git a/Source/resolver/ResolvedPostgresServerResource.ts b/Source/resolver/ResolvedPostgresServerResource.ts index a1e35acf3..76007eac0 100644 --- a/Source/resolver/ResolvedPostgresServerResource.ts +++ b/Source/resolver/ResolvedPostgresServerResource.ts @@ -4,45 +4,54 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { ClientConfig } from "pg"; import { PostgresServerType } from "../postgres/abstract/models"; import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise - deletePostgresCredentials: () => Promise - getFullConnectionString: () => Promise - validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise - isFirewallRuleSet: (context: IActionContext) => Promise - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } +export class ResolvedPostgresServerResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public readonly serverType?: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + setCredentials: (username: string, password: string) => void; + supportsStoredProcedures: (clientConfig: ClientConfig) => Promise; + deletePostgresCredentials: () => Promise; + getFullConnectionString: () => Promise; + validateDatabaseName: ( + name: string, + getChildrenTask: Promise + ) => Promise; + isFirewallRuleSet: (context: IActionContext) => Promise; + + public constructor(ti: PostgresServerTreeItem, resource: AppResource) { + super(ti, resource); + this.serverType = ti.serverType; + this.description = ti.description; + this.resourceGroup = ti.resourceGroup; + this.azureName = ti.azureName; + this.partialConnectionString = ti.partialConnectionString; + + this.azureId = ti.azureId; + this.serverVersion = ti.serverVersion; + + this.setCredentials = ti.setCredentials; + this.supportsStoredProcedures = ti.supportsStoredProcedures; + this.deletePostgresCredentials = ti.deletePostgresCredentials; + this.getFullConnectionString = ti.getFullConnectionString; + this.isFirewallRuleSet = ti.isFirewallRuleSet; + } } diff --git a/Source/table/tree/TableAccountTreeItem.ts b/Source/table/tree/TableAccountTreeItem.ts index 0d3b86e38..fb2616da9 100644 --- a/Source/table/tree/TableAccountTreeItem.ts +++ b/Source/table/tree/TableAccountTreeItem.ts @@ -4,36 +4,40 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBTableAccount"; + public contextValue: string = TableAccountTreeItem.contextValue; - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public initChild(): AzExtTreeItem { - throw new Error('Table Accounts are not supported yet.'); - } + public initChild(): AzExtTreeItem { + throw new Error("Table Accounts are not supported yet."); + } - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'tableNotSupported', - label: 'Table Accounts are not supported yet.' - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: "tableNotSupported", + label: "Table Accounts are not supported yet.", + }); + tableNotFoundTreeItem.suppressMaskLabel = true; + return [tableNotFoundTreeItem]; + } - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } - public isAncestorOfImpl(): boolean { - return false; - } + public isAncestorOfImpl(): boolean { + return false; + } } diff --git a/Source/tree/AttachedAccountsTreeItem.ts b/Source/tree/AttachedAccountsTreeItem.ts index d854e506f..47aa8bdc3 100644 --- a/Source/tree/AttachedAccountsTreeItem.ts +++ b/Source/tree/AttachedAccountsTreeItem.ts @@ -3,418 +3,605 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { removeTreeItemFromCache } from '../commands/api/apiCache'; -import { emulatorPassword, isWindows } from '../constants'; -import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; -import { connectToMongoClient } from '../mongo/connectToMongoClient'; -import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; -import { getSecretStorageKey } from '../utils/getSecretStorageKey'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + AzExtTreeItem, + GenericTreeItem, + IActionContext, + ISubscriptionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { MongoClient } from "mongodb"; +import * as vscode from "vscode"; +import { + API, + getExperienceFromApi, + getExperienceQuickPick, + getExperienceQuickPicks, +} from "../AzureDBExperiences"; +import { removeTreeItemFromCache } from "../commands/api/apiCache"; +import { emulatorPassword, isWindows } from "../constants"; +import { parseDocDBConnectionString } from "../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; +import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../extensionVariables"; +import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; +import { connectToMongoClient } from "../mongo/connectToMongoClient"; +import { parseMongoConnectionString } from "../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { parsePostgresConnectionString } from "../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; +import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; +import { getSecretStorageKey } from "../utils/getSecretStorageKey"; +import { localize } from "../utils/localize"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; + id: string; + // defaultExperience is not the same as API but we can't change the name due to backwards compatibility + defaultExperience: API; + isEmulator: boolean | undefined; } -export const AttachedAccountSuffix: string = 'Attached'; -export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; +export const AttachedAccountSuffix: string = "Attached"; +export const MONGO_CONNECTION_EXPECTED: string = + 'Connection string must start with "mongodb://" or "mongodb+srv://"'; -const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; +const localMongoConnectionString: string = "mongodb://127.0.0.1:27017"; export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); - public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; - public readonly label: string = 'Attached Database Accounts'; - public childTypeLabel: string = 'Account'; - public suppressMaskLabel = true; - - private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = 'cosmosDBAttachedAccounts'; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('plug'); - } - - public static validateMongoConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); - } - - private static validateDocDBConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachDatabaseAccount', - label: 'Attach Database Account...', - commandId: 'cosmosDB.attachDatabaseAccount', - includeInTreeItemPicker: true - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachEmulator', - label: 'Attach Emulator...', - commandId: 'cosmosDB.attachEmulator', - includeInTreeItemPicker: true - }); - return isWindows ? [attachDatabaseAccount, attachEmulator] : - [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = 'mongodb://host:port'; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; - } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { - placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); - validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = 'AccountEndpoint=...;AccountKey=...'; - validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = (await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: 'Enter the connection string for your database account', - stepName: 'attachNewAccountConnectionString', - validateInput: validateInput, - value: defaultValue - })).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { - const treeItem = await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core) - ], - { - placeHolder: "Select a Database Account API...", - stepName: 'attachEmulator' - }); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); - if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.find(s => s.id === treeItem.id)) { - void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get(this._serviceName); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all(accounts.map(async account => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof (account) === 'string') { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${getExperienceFromApi(api).shortName})`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); - persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); - })); - } - - return persistedAccounts; - } - - private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error(`Unexpected account node "${node.constructor.name}".`); - } - return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; - }); - await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); - } + public static contextValue: string = + "cosmosDBAttachedAccounts" + + (isWindows ? "WithEmulator" : "WithoutEmulator"); + public readonly contextValue: string = + AttachedAccountsTreeItem.contextValue; + public readonly label: string = "Attached Database Accounts"; + public childTypeLabel: string = "Account"; + public suppressMaskLabel = true; + + private readonly _serviceName: string = + "ms-azuretools.vscode-cosmosdb.connectionStrings"; + private _attachedAccounts: AzExtTreeItem[] | undefined; + + private _root: ISubscriptionContext; + private _loadPersistedAccountsTask: Promise; + + constructor(parent: AzExtParentTreeItem) { + super(parent); + this._root = new AttachedAccountRoot(); + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + this.id = "cosmosDBAttachedAccounts"; + } + + public get root(): ISubscriptionContext { + return this._root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("plug"); + } + + public static validateMongoConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + if (value && value.match(/^mongodb(\+srv)?:\/\//)) { + return undefined; + } + + return MONGO_CONNECTION_EXPECTED; + } + + public static validatePostgresConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + if (value && value.match(/^postgres:\/\//)) { + return undefined; + } + + return localize( + "invalidPostgresConnectionString", + 'Connection string must start with "postgres://"' + ); + } + + private static validateDocDBConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + try { + parseDocDBConnectionString(value); + return undefined; + } catch (error) { + return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache) { + this._attachedAccounts = undefined; + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + } + + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + if (attachedAccounts.length > 0) { + return attachedAccounts; + } else { + const attachDatabaseAccount = new GenericTreeItem(this, { + contextValue: "cosmosDBAttachDatabaseAccount", + label: "Attach Database Account...", + commandId: "cosmosDB.attachDatabaseAccount", + includeInTreeItemPicker: true, + }); + const attachEmulator = new GenericTreeItem(this, { + contextValue: "cosmosDBAttachEmulator", + label: "Attach Emulator...", + commandId: "cosmosDB.attachEmulator", + includeInTreeItemPicker: true, + }); + return isWindows + ? [attachDatabaseAccount, attachEmulator] + : [attachDatabaseAccount]; + } + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + // We have to make sure the Attached Accounts node is not shown for commands like + // 'Open in Portal', which only work for the non-attached version + case GraphAccountTreeItem.contextValue: + case MongoAccountTreeItem.contextValue: + case DocDBAccountTreeItem.contextValue: + case TableAccountTreeItem.contextValue: + case PostgresServerTreeItem.contextValue: + case SubscriptionTreeItem.contextValue: + return false; + default: + return true; + } + } + + public async attachNewAccount(context: IActionContext): Promise { + const defaultExperiencePick = await context.ui.showQuickPick( + getExperienceQuickPicks(true), + { + placeHolder: "Select a Database type...", + stepName: "attachNewAccount", + } + ); + const defaultExperience = defaultExperiencePick.data; + let placeholder: string; + let defaultValue: string | undefined; + let validateInput: (value: string) => string | undefined | null; + if (defaultExperience.api === API.MongoDB) { + placeholder = "mongodb://host:port"; + if (await this.canConnectToLocalMongoDB()) { + defaultValue = placeholder = localMongoConnectionString; + } + validateInput = + AttachedAccountsTreeItem.validateMongoConnectionString; + } else if ( + defaultExperience.api === API.PostgresSingle || + defaultExperience.api === API.PostgresFlexible + ) { + placeholder = localize( + "attachedPostgresPlaceholder", + '"postgres://username:password@host" or "postgres://username:password@host/database"' + ); + validateInput = + AttachedAccountsTreeItem.validatePostgresConnectionString; + } else { + placeholder = "AccountEndpoint=...;AccountKey=..."; + validateInput = + AttachedAccountsTreeItem.validateDocDBConnectionString; + } + + const connectionString = ( + await context.ui.showInputBox({ + placeHolder: placeholder, + prompt: "Enter the connection string for your database account", + stepName: "attachNewAccountConnectionString", + validateInput: validateInput, + value: defaultValue, + }) + ).trim(); + + const treeItem: AzExtTreeItem = await this.createTreeItem( + connectionString, + defaultExperience.api + ); + await this.attachAccount(context, treeItem, connectionString); + } + + public async attachConnectionString( + context: IActionContext, + connectionString: string, + api: API.MongoDB | API.Core | API.PostgresSingle + ): Promise< + MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem + > { + const treeItem = < + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + >await this.createTreeItem(connectionString, api); + await this.attachAccount(context, treeItem, connectionString); + await this.refresh(context); + return treeItem; + } + + public async attachEmulator(context: IActionContext): Promise { + let connectionString: string; + const defaultExperiencePick = await context.ui.showQuickPick( + [ + getExperienceQuickPick(API.MongoDB), + getExperienceQuickPick(API.Core), + ], + { + placeHolder: "Select a Database Account API...", + stepName: "attachEmulator", + } + ); + const defaultExperience = defaultExperiencePick.data; + let port: number | undefined; + if (defaultExperience.api === API.MongoDB) { + port = vscode.workspace + .getConfiguration() + .get("cosmosDB.emulator.mongoPort"); + } else { + port = vscode.workspace + .getConfiguration() + .get("cosmosDB.emulator.port"); + } + if (port) { + if (defaultExperience.api === API.MongoDB) { + // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions + connectionString = `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:${port}/?ssl=true`; + } else { + connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; + } + const label = `${defaultExperience.shortName} Emulator`; + const treeItem: AzExtTreeItem = await this.createTreeItem( + connectionString, + defaultExperience.api, + label + ); + if ( + treeItem instanceof DocDBAccountTreeItem || + treeItem instanceof GraphAccountTreeItem || + treeItem instanceof TableAccountTreeItem || + treeItem instanceof MongoAccountTreeItem + ) { + // CONSIDER: Why isn't this passed in to createTreeItem above? + treeItem.root.isEmulator = true; + } + await this.attachAccount(context, treeItem, connectionString); + } + } + + public async detach(node: AzExtTreeItem): Promise { + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + const index = attachedAccounts.findIndex( + (account) => account.fullId === node.fullId + ); + if (index !== -1) { + attachedAccounts.splice(index, 1); + await ext.secretStorage.delete( + getSecretStorageKey(this._serviceName, nonNullProp(node, "id")) + ); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility + await this.persistIds(attachedAccounts); + + if (node instanceof MongoAccountTreeItem) { + const parsedCS = await parseMongoConnectionString( + node.connectionString + ); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof DocDBAccountTreeItemBase) { + const parsedCS = parseDocDBConnectionString( + node.connectionString + ); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof PostgresServerTreeItem) { + const parsedCS = node.partialConnectionString; + removeTreeItemFromCache(parsedCS); + } + } + } + + private async getAttachedAccounts(): Promise { + if (!this._attachedAccounts) { + try { + this._attachedAccounts = await this._loadPersistedAccountsTask; + } catch { + this._attachedAccounts = []; + throw new Error( + "Failed to load persisted Database Accounts. Reattach the accounts manually." + ); + } + } + + return this._attachedAccounts; + } + + private async canConnectToLocalMongoDB(): Promise { + async function timeout(): Promise { + await delay(1000); + return false; + } + async function connect(): Promise { + try { + const db: MongoClient = await connectToMongoClient( + localMongoConnectionString, + appendExtensionUserAgent() + ); + void db.close(); + return true; + } catch { + return false; + } + } + return await Promise.race([timeout(), connect()]); + } + + private async attachAccount( + context: IActionContext, + treeItem: AzExtTreeItem, + connectionString: string + ): Promise { + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + if (attachedAccounts.find((s) => s.id === treeItem.id)) { + void context.ui.showWarningMessage( + `Database Account '${treeItem.id}' is already attached.`, + { stepName: "attachAccount" } + ); + } else { + attachedAccounts.push(treeItem); + await ext.secretStorage.store( + getSecretStorageKey( + this._serviceName, + nonNullProp(treeItem, "id") + ), + connectionString + ); + await this.persistIds(attachedAccounts); + } + } + + private async loadPersistedAccounts(): Promise { + const persistedAccounts: AzExtTreeItem[] = []; + const value: string | undefined = ext.context.globalState.get( + this._serviceName + ); + if (value) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const accounts: (string | IPersistedAccount)[] = JSON.parse(value); + await Promise.all( + accounts.map(async (account) => { + let id: string; + let label: string; + let api: API; + let isEmulator: boolean | undefined; + if (typeof account === "string") { + // Default to Mongo if the value is a string for the sake of backwards compatibility + // (Mongo was originally the only account type that could be attached) + id = account; + api = API.MongoDB; + label = `${account} (${ + getExperienceFromApi(api).shortName + })`; + isEmulator = false; + } else { + id = (account).id; + api = (account).defaultExperience; + isEmulator = (account).isEmulator; + label = isEmulator + ? `${getExperienceFromApi(api).shortName} Emulator` + : `${id} (${getExperienceFromApi(api).shortName})`; + } + // TODO: keytar: migration plan? + const connectionString: string = nonNullValue( + await ext.secretStorage.get( + getSecretStorageKey(this._serviceName, id) + ), + "connectionString" + ); + persistedAccounts.push( + await this.createTreeItem( + connectionString, + api, + label, + id, + isEmulator + ) + ); + }) + ); + } + + return persistedAccounts; + } + + private async createTreeItem( + connectionString: string, + api: API, + label?: string, + id?: string, + isEmulator?: boolean + ): Promise { + let treeItem: AzExtTreeItem; + if (api === API.MongoDB) { + if (id === undefined) { + const parsedCS = + await parseMongoConnectionString(connectionString); + id = parsedCS.fullId; + } + + label = label || `${id} (${getExperienceFromApi(api).shortName})`; + treeItem = new MongoAccountTreeItem( + this, + id, + label, + connectionString, + isEmulator + ); + } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { + const parsedPostgresConnString = + parsePostgresConnectionString(connectionString); + treeItem = new PostgresServerTreeItem( + this, + parsedPostgresConnString + ); + } else { + const parsedCS = parseDocDBConnectionString(connectionString); + + label = + label || + `${parsedCS.accountId} (${ + getExperienceFromApi(api).shortName + })`; + switch (api) { + case API.Table: + treeItem = new TableAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + parsedCS.masterKey, + isEmulator + ); + break; + case API.Graph: + treeItem = new GraphAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + undefined, + parsedCS.masterKey, + isEmulator + ); + break; + case API.Core: + treeItem = new DocDBAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + parsedCS.masterKey, + isEmulator + ); + break; + default: + throw new Error(`Unexpected defaultExperience "${api}".`); + } + } + + treeItem.contextValue += AttachedAccountSuffix; + return treeItem; + } + + private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { + const value: IPersistedAccount[] = attachedAccounts.map( + (node: AzExtTreeItem) => { + let api: API; + let isEmulator: boolean | undefined; + if ( + node instanceof MongoAccountTreeItem || + node instanceof DocDBAccountTreeItem || + node instanceof GraphAccountTreeItem || + node instanceof TableAccountTreeItem + ) { + isEmulator = node.root.isEmulator; + } + if (node instanceof MongoAccountTreeItem) { + api = API.MongoDB; + } else if (node instanceof GraphAccountTreeItem) { + api = API.Graph; + } else if (node instanceof TableAccountTreeItem) { + api = API.Table; + } else if (node instanceof DocDBAccountTreeItem) { + api = API.Core; + } else if (node instanceof PostgresServerTreeItem) { + api = API.PostgresSingle; + } else { + throw new Error( + `Unexpected account node "${node.constructor.name}".` + ); + } + return { + id: nonNullProp(node, "id"), + defaultExperience: api, + isEmulator: isEmulator, + }; + } + ); + await ext.context.globalState.update( + this._serviceName, + JSON.stringify(value) + ); + } } class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); + private _error: Error = new Error( + "Cannot retrieve Azure subscription information for an attached account." + ); - public get credentials(): never { - throw this._error; - } + public get credentials(): never { + throw this._error; + } - public get subscriptionDisplayName(): never { - throw this._error; - } + public get subscriptionDisplayName(): never { + throw this._error; + } - public get subscriptionId(): never { - throw this._error; - } + public get subscriptionId(): never { + throw this._error; + } - public get subscriptionPath(): never { - throw this._error; - } + public get subscriptionPath(): never { + throw this._error; + } - public get tenantId(): never { - throw this._error; - } + public get tenantId(): never { + throw this._error; + } - public get userId(): never { - throw this._error; - } + public get userId(): never { + throw this._error; + } - public get environment(): never { - throw this._error; - } + public get environment(): never { + throw this._error; + } - public get isCustomCloud(): never { - throw this._error; - } + public get isCustomCloud(): never { + throw this._error; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/tree/AzureAccountTreeItemWithAttached.ts b/Source/tree/AzureAccountTreeItemWithAttached.ts index 172cd598f..ce1cdb8fd 100644 --- a/Source/tree/AzureAccountTreeItemWithAttached.ts +++ b/Source/tree/AzureAccountTreeItemWithAttached.ts @@ -3,34 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; -import { ext } from '../extensionVariables'; -import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; +import { AzureAccountTreeItemBase } from "@microsoft/vscode-azext-azureutils"; +import { + AzExtTreeItem, + IActionContext, + ISubscriptionContext, +} from "@microsoft/vscode-azext-utils"; +import { ext } from "../extensionVariables"; +import { AttachedAccountsTreeItem } from "./AttachedAccountsTreeItem"; +import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } + public constructor(testAccount?: {}) { + super(undefined, testAccount); + ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); + } - public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } + public createSubscriptionTreeItem( + root: ISubscriptionContext + ): SubscriptionTreeItem { + return new SubscriptionTreeItem(this, root); + } - public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); - return children.concat(ext.attachedAccountsNode); - } + public async loadMoreChildrenImpl( + clearCache: boolean, + context: IActionContext + ): Promise { + const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl( + clearCache, + context + ); + return children.concat(ext.attachedAccountsNode); + } - public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } + public compareChildrenImpl( + item1: AzExtTreeItem, + item2: AzExtTreeItem + ): number { + if (item1 instanceof AttachedAccountsTreeItem) { + return 1; + } else if (item2 instanceof AttachedAccountsTreeItem) { + return -1; + } else { + return super.compareChildrenImpl(item1, item2); + } + } } diff --git a/Source/tree/AzureDBAPIStep.ts b/Source/tree/AzureDBAPIStep.ts index 8a11fdc95..a59ebfd48 100644 --- a/Source/tree/AzureDBAPIStep.ts +++ b/Source/tree/AzureDBAPIStep.ts @@ -3,74 +3,103 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; -import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; -import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; -import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; -import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; -import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; -import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; -import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; -import { localize } from '../utils/localize'; -import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; -import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; -import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; -import { IAzureDBWizardContext } from './IAzureDBWizardContext'; +import { VerifyProvidersStep } from "@microsoft/vscode-azext-azureutils"; +import { + AzureWizardExecuteStep, + AzureWizardPromptStep, + IAzureQuickPickItem, + IWizardOptions, +} from "@microsoft/vscode-azext-utils"; +import { + API, + Experience, + getExperienceQuickPicks, +} from "../AzureDBExperiences"; +import { PostgresServerType } from "../postgres/abstract/models"; +import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; +import { PostgresServerConfirmPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep"; +import { PostgresServerCreateStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep"; +import { PostgresServerCredPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep"; +import { PostgresServerCredUserStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep"; +import { PostgresServerNameStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerNameStep"; +import { PostgresServerSetCredentialsStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep"; +import { PostgresServerSkuStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep"; +import { localize } from "../utils/localize"; +import { CosmosDBAccountCapacityStep } from "./CosmosDBAccountWizard/CosmosDBAccountCapacityStep"; +import { CosmosDBAccountCreateStep } from "./CosmosDBAccountWizard/CosmosDBAccountCreateStep"; +import { CosmosDBAccountNameStep } from "./CosmosDBAccountWizard/CosmosDBAccountNameStep"; +import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; +import { IAzureDBWizardContext } from "./IAzureDBWizardContext"; -export class AzureDBAPIStep extends AzureWizardPromptStep { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); +export class AzureDBAPIStep extends AzureWizardPromptStep< + IPostgresServerWizardContext | ICosmosDBWizardContext +> { + public async prompt(context: IAzureDBWizardContext): Promise { + const picks: IAzureQuickPickItem[] = + getExperienceQuickPicks(); - const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { - placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') - }); + const result: IAzureQuickPickItem = + await context.ui.showQuickPick(picks, { + placeHolder: localize( + "selectDBServerMsg", + "Select an Azure Database Server." + ), + }); - context.defaultExperience = result.data; - } + context.defaultExperience = result.data; + } - public async getSubWizard(context: IAzureDBWizardContext): Promise> { - let promptSteps: AzureWizardPromptStep[]; - let executeSteps: AzureWizardExecuteStep[]; - if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(['Microsoft.DocumentDB']) - ]; - } - return { promptSteps, executeSteps }; - } + public async getSubWizard( + context: IAzureDBWizardContext + ): Promise< + IWizardOptions + > { + let promptSteps: AzureWizardPromptStep< + IPostgresServerWizardContext | ICosmosDBWizardContext + >[]; + let executeSteps: AzureWizardExecuteStep< + IPostgresServerWizardContext | ICosmosDBWizardContext + >[]; + if ( + context.defaultExperience?.api === API.PostgresSingle || + context.defaultExperience?.api === API.PostgresFlexible + ) { + switch (context.defaultExperience?.api) { + case API.PostgresFlexible: + (context as IPostgresServerWizardContext).serverType = + PostgresServerType.Flexible; + break; + case API.PostgresSingle: + (context as IPostgresServerWizardContext).serverType = + PostgresServerType.Single; + break; + } + promptSteps = [ + new PostgresServerNameStep(), + new PostgresServerSkuStep(), + new PostgresServerCredUserStep(), + new PostgresServerCredPWStep(), + new PostgresServerConfirmPWStep(), + ]; + executeSteps = [ + new PostgresServerCreateStep(), + new PostgresServerSetCredentialsStep(), + new VerifyProvidersStep(["Microsoft.DBforPostgreSQL"]), + ]; + } else { + promptSteps = [ + new CosmosDBAccountNameStep(), + new CosmosDBAccountCapacityStep(), + ]; + executeSteps = [ + new CosmosDBAccountCreateStep(), + new VerifyProvidersStep(["Microsoft.DocumentDB"]), + ]; + } + return { promptSteps, executeSteps }; + } - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } + public shouldPrompt(context: IAzureDBWizardContext): boolean { + return !context.defaultExperience; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts index b46453e3a..192e5fa54 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts @@ -3,38 +3,53 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, +} from "@microsoft/vscode-azext-utils"; +import { localize } from "../../utils/localize"; +import { openUrl } from "../../utils/openUrl"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { + public async prompt(context: ICosmosDBWizardContext): Promise { + const placeHolder: string = localize( + "selectDBServerMsg", + "Select a capacity model." + ); + const picks: IAzureQuickPickItem[] = [ + { + label: localize("provisionedOption", "Provisioned Throughput"), + data: false, + }, + { label: localize("serverlessOption", "Serverless"), data: true }, + ]; + const learnMore: IAzureQuickPickItem = { + label: localize("learnMore", "$(link-external) Learn more..."), + data: undefined, + }; + picks.push(learnMore); + let pick: IAzureQuickPickItem; - public async prompt(context: ICosmosDBWizardContext): Promise { + do { + pick = await context.ui.showQuickPick(picks, { + placeHolder, + suppressPersistence: true, + }); + if (pick === learnMore) { + await openUrl("https://aka.ms/cosmos-models"); + } + } while (pick === learnMore); - const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') - const picks: IAzureQuickPickItem[] = [ - { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, - { label: localize('serverlessOption', 'Serverless'), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; + if (pick.data) { + context.isServerless = pick.data; + context.telemetry.properties.isServerless = pick.data + ? "true" + : "false"; + } + } - do { - pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); - if (pick === learnMore) { - await openUrl('https://aka.ms/cosmos-models'); - } - } while (pick === learnMore); - - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; - } - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return context.isServerless === undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts index 4bd469b84..f0eadf3a3 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts @@ -3,61 +3,81 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; -import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { Progress } from 'vscode'; -import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { DatabaseAccountCreateUpdateParameters } from "@azure/arm-cosmosdb/src/models"; +import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; +import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; +import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; +import { Progress } from "vscode"; +import { SERVERLESS_CAPABILITY_NAME } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const locationName: string = (await LocationListStep.getLocation(context)).name; - const defaultExperience = nonNullProp(context, 'defaultExperience'); - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const accountName = nonNullProp(context, 'newServerName'); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: 'Standard', - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, - }; - - if (defaultExperience?.api === 'MongoDB') { - options.apiProperties = { serverVersion: '3.6' }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } + public priority: number = 130; + + public async execute( + context: ICosmosDBWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + const locationName: string = ( + await LocationListStep.getLocation(context) + ).name; + const defaultExperience = nonNullProp(context, "defaultExperience"); + const rgName: string = nonNullProp( + nonNullProp(context, "resourceGroup"), + "name" + ); + const accountName = nonNullProp(context, "newServerName"); + + const client = await createCosmosDBClient(context); + const creatingMessage: string = localize( + "creatingCosmosDBAccount", + 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', + accountName, + defaultExperience.shortName + ); + ext.outputChannel.appendLog(creatingMessage); + progress.report({ message: creatingMessage }); + + const options: DatabaseAccountCreateUpdateParameters = { + location: locationName, + locations: [{ locationName: locationName }], + kind: defaultExperience.kind, + capabilities: [], + databaseAccountOfferType: "Standard", + // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior + tags: { defaultExperience: nonNullProp(defaultExperience, "tag") }, + }; + + if (defaultExperience?.api === "MongoDB") { + options.apiProperties = { serverVersion: "3.6" }; + } + + if (defaultExperience.capability) { + options.capabilities?.push({ name: defaultExperience.capability }); + } + + if (context.isServerless) { + options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); + } + + context.databaseAccount = + await client.databaseAccounts.beginCreateOrUpdateAndWait( + rgName, + accountName, + options + ); + context.activityResult = context.databaseAccount as AppResource; + + ext.outputChannel.appendLog( + `Successfully created Cosmos DB account "${accountName}".` + ); + } + + public shouldExecute(context: ICosmosDBWizardContext): boolean { + return !context.databaseAccount; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts index 87ef6be61..222736605 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts @@ -3,47 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { + ResourceGroupListStep, + resourceGroupNamingRules, +} from "@microsoft/vscode-azext-azureutils"; +import { AzureNameStep } from "@microsoft/vscode-azext-utils"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountNameStep extends AzureNameStep { + public async prompt(context: ICosmosDBWizardContext): Promise { + const client = await createCosmosDBClient(context); + context.newServerName = ( + await context.ui.showInputBox({ + placeHolder: "Account name", + prompt: "Provide a Cosmos DB account name", + validateInput: (name: string) => + validateCosmosDBAccountName(name, client), + }) + ).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName( + context, + context.newServerName, + resourceGroupNamingRules + ); + } - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => validateCosmosDBAccountName(name, client) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return !context.newServerName; + } - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + protected async isRelatedNameAvailable( + context: ICosmosDBWizardContext, + name: string + ): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { - name = name ? name.trim() : ''; +async function validateCosmosDBAccountName( + name: string, + client: CosmosDBManagementClient +): Promise { + name = name ? name.trim() : ""; - const min = 3; - const max = 31; + const min = 3; + const max = 31; - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } + if (name.length < min || name.length > max) { + return `The name must be between ${min} and ${max} characters.`; + } else if (name.match(/[^a-z0-9-]/)) { + return "The name can only contain lowercase letters, numbers, and the '-' character."; + } else if ((await client.databaseAccounts.checkNameExists(name)).body) { + return `Account name "${name}" is not available.`; + } else { + return undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts index 61666a859..cc12a75ed 100644 --- a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; - -export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb"; +import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; +import { IAzureDBWizardContext } from "../IAzureDBWizardContext"; +export interface ICosmosDBWizardContext + extends IAzureDBWizardContext, + ExecuteActivityContext { + /** + * The newly created Cosmos DB account + * This will be defined after `CosmosDBAccountStep.execute` occurs. + */ + databaseAccount?: DatabaseAccountGetResults; + isServerless?: boolean; } diff --git a/Source/tree/IAzureDBWizardContext.ts b/Source/tree/IAzureDBWizardContext.ts index fd84ff0d5..5f6946275 100644 --- a/Source/tree/IAzureDBWizardContext.ts +++ b/Source/tree/IAzureDBWizardContext.ts @@ -3,12 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { Experience } from '../AzureDBExperiences'; +import { IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; +import { Experience } from "../AzureDBExperiences"; export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - - newServerName?: string; - defaultExperience?: Experience; - + newServerName?: string; + defaultExperience?: Experience; } diff --git a/Source/tree/SubscriptionTreeItem.ts b/Source/tree/SubscriptionTreeItem.ts index 910d8d970..93cb2173a 100644 --- a/Source/tree/SubscriptionTreeItem.ts +++ b/Source/tree/SubscriptionTreeItem.ts @@ -3,156 +3,322 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; -import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { + DatabaseAccountGetResults, + DatabaseAccountListKeysResult, +} from "@azure/arm-cosmosdb/src/models"; +import { + getResourceGroupFromId, + ILocationWizardContext, + LocationListStep, + ResourceGroupListStep, + SubscriptionTreeItemBase, + uiUtils, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + AzureWizard, + AzureWizardPromptStep, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { + API, + Experience, + getExperienceLabel, + tryGetExperience, +} from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from '../extensionVariables'; -import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; +import { ext } from "../extensionVariables"; +import { tryGetGremlinEndpointFromAzure } from "../graph/gremlinEndpoints"; import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { + PostgresAbstractServer, + PostgresServerType, +} from "../postgres/abstract/models"; +import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; +import { + createPostgresConnectionString, + ParsedPostgresConnectionString, + parsePostgresConnectionString, +} from "../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from '../utils/activityUtils'; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { localize } from '../utils/localize'; -import { nonNullProp } from '../utils/nonNull'; -import { AzureDBAPIStep } from './AzureDBAPIStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; +import { createActivityContext } from "../utils/activityUtils"; +import { + createCosmosDBClient, + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../utils/azureClients"; +import { localize } from "../utils/localize"; +import { nonNullProp } from "../utils/nonNull"; +import { AzureDBAPIStep } from "./AzureDBAPIStep"; +import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = 'Account'; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - - //Postgres - const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); - const postgresServers: PostgresAbstractServer[] = [ - ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), - ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), - ]; - - const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - postgresServers, - 'invalidPostgreSQLAccount', - async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); - const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - accounts, - 'invalidCosmosDBAccount', - async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep() - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize('createDBServerMsg', 'Create new Azure Database Server') - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp(wizardContext, 'newServerName'); - wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { - const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, 'server'); - const host = nonNullProp(server, 'fullyQualifiedDomainName'); - const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); - const password: string = nonNullProp(wizardContext, 'adminPassword'); - const connectionString: string = createPostgresConnectionString(host, undefined, username, password); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return typeof contextValue !== 'string' || !/attached/i.test(contextValue); - } - - public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, 'id'); - const name: string = nonNullProp(databaseAccount, 'name'); - const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); - const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = 'retrywrites'; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, 'false'); - } - - // Use the default connection string - return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); - } else { - const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - case "Graph": { - const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); - return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - - } - } - } - public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { - const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } + public childTypeLabel: string = "Account"; + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + //Postgres + const postgresSingleClient = await createPostgreSQLClient([ + context, + this.subscription, + ]); + const postgresFlexibleClient = await createPostgreSQLFlexibleClient([ + context, + this.subscription, + ]); + const postgresServers: PostgresAbstractServer[] = [ + ...( + await uiUtils.listAllIterator( + postgresSingleClient.servers.list() + ) + ).map((s) => + Object.assign(s, { serverType: PostgresServerType.Single }) + ), + ...( + await uiUtils.listAllIterator( + postgresFlexibleClient.servers.list() + ) + ).map((s) => + Object.assign(s, { serverType: PostgresServerType.Flexible }) + ), + ]; + + const treeItemPostgres: AzExtTreeItem[] = + await this.createTreeItemsWithErrorHandling( + postgresServers, + "invalidPostgreSQLAccount", + async (server: PostgresAbstractServer) => + await SubscriptionTreeItem.initPostgresChild(server, this), + (server: PostgresAbstractServer) => server.name + ); + + //CosmosDB + const client = await createCosmosDBClient([context, this]); + const accounts = await uiUtils.listAllIterator( + client.databaseAccounts.list() + ); + const treeItem: AzExtTreeItem[] = + await this.createTreeItemsWithErrorHandling( + accounts, + "invalidCosmosDBAccount", + async (db: DatabaseAccountGetResults) => + await SubscriptionTreeItem.initCosmosDBChild( + client, + db, + this + ), + (db: DatabaseAccountGetResults) => db.name + ); + + treeItem.push(...treeItemPostgres); + return treeItem; + } + + public static async createChild( + context: IActionContext & { defaultExperience?: Experience }, + node: SubscriptionTreeItem + ): Promise { + const client = await createCosmosDBClient([context, node.subscription]); + const wizardContext: IPostgresServerWizardContext & + ICosmosDBWizardContext = Object.assign(context, node.subscription, { + ...(await createActivityContext()), + }); + + const promptSteps: AzureWizardPromptStep[] = [ + new AzureDBAPIStep(), + new ResourceGroupListStep(), + ]; + LocationListStep.addStep(wizardContext, promptSteps); + + const wizard = new AzureWizard(wizardContext, { + promptSteps, + executeSteps: [], + title: localize( + "createDBServerMsg", + "Create new Azure Database Server" + ), + }); + + await wizard.prompt(); + + wizardContext.telemetry.properties.defaultExperience = + wizardContext.defaultExperience?.api; + + const newServerName: string = nonNullProp( + wizardContext, + "newServerName" + ); + wizardContext.activityTitle = localize( + "createDBServerMsgActivityTitle", + 'Create new Azure Database Server "{0}"', + newServerName + ); + + await wizard.execute(); + await ext.rgApi.appResourceTree.refresh(context); + if ( + wizardContext.defaultExperience?.api === API.PostgresSingle || + wizardContext.defaultExperience?.api === API.PostgresFlexible + ) { + const createMessage: string = localize( + "createdServerOutput", + 'Successfully created PostgreSQL server "{0}".', + wizardContext.newServerName + ); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); + const server = nonNullProp(wizardContext, "server"); + const host = nonNullProp(server, "fullyQualifiedDomainName"); + const username: string = + wizardContext.serverType === PostgresServerType.Flexible + ? nonNullProp(wizardContext, "shortUserName") + : nonNullProp(wizardContext, "longUserName"); + const password: string = nonNullProp( + wizardContext, + "adminPassword" + ); + const connectionString: string = createPostgresConnectionString( + host, + undefined, + username, + password + ); + const parsedCS: ParsedPostgresConnectionString = + parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(node, parsedCS, server); + } else { + return await SubscriptionTreeItem.initCosmosDBChild( + client, + nonNullProp(wizardContext, "databaseAccount"), + node + ); + } + } + + public isAncestorOfImpl(contextValue: string | RegExp): boolean { + return ( + typeof contextValue !== "string" || !/attached/i.test(contextValue) + ); + } + + public static async initCosmosDBChild( + client: CosmosDBManagementClient, + databaseAccount: DatabaseAccountGetResults, + parent: AzExtParentTreeItem + ): Promise { + const experience = tryGetExperience(databaseAccount); + const id: string = nonNullProp(databaseAccount, "id"); + const name: string = nonNullProp(databaseAccount, "name"); + const documentEndpoint: string = nonNullProp( + databaseAccount, + "documentEndpoint" + ); + + const resourceGroup: string = getResourceGroupFromId(id); + const accountKindLabel = getExperienceLabel(databaseAccount); + const label: string = + name + (accountKindLabel ? ` (${accountKindLabel})` : ``); + const isEmulator: boolean = false; + + if (experience && experience.api === "MongoDB") { + const result = await client.databaseAccounts.listConnectionStrings( + resourceGroup, + name + ); + const connectionString: URL = new URL( + nonNullProp( + nonNullProp(result, "connectionStrings")[0], + "connectionString" + ) + ); + // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites + // but the newer node.js drivers started breaking this + const searchParam: string = "retrywrites"; + if (!connectionString.searchParams.has(searchParam)) { + connectionString.searchParams.set(searchParam, "false"); + } + + // Use the default connection string + return new MongoAccountTreeItem( + parent, + id, + label, + connectionString.toString(), + isEmulator, + databaseAccount + ); + } else { + const keyResult: DatabaseAccountListKeysResult = + await client.databaseAccounts.listKeys(resourceGroup, name); + const primaryMasterKey: string = nonNullProp( + keyResult, + "primaryMasterKey" + ); + switch (experience && experience.api) { + case "Table": + return new TableAccountTreeItem( + parent, + id, + label, + documentEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + case "Graph": { + const gremlinEndpoint = + await tryGetGremlinEndpointFromAzure( + client, + resourceGroup, + name + ); + return new GraphAccountTreeItem( + parent, + id, + label, + documentEndpoint, + gremlinEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + } + case "Core": + default: + // Default to DocumentDB, the base type for all Cosmos DB Accounts + return new DocDBAccountTreeItem( + parent, + id, + label, + documentEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + } + } + } + public static async initPostgresChild( + server: PostgresAbstractServer, + parent: AzExtParentTreeItem + ): Promise { + const connectionString: string = createPostgresConnectionString( + nonNullProp(server, "fullyQualifiedDomainName") + ); + const parsedCS: ParsedPostgresConnectionString = + parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(parent, parsedCS, server); + } } diff --git a/Source/utils/InteractiveChildProcess.ts b/Source/utils/InteractiveChildProcess.ts index 26129b342..1cd1848e5 100644 --- a/Source/utils/InteractiveChildProcess.ts +++ b/Source/utils/InteractiveChildProcess.ts @@ -3,174 +3,194 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as cp from 'child_process'; -import * as os from 'os'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { Event, EventEmitter } from 'vscode'; -import { improveError } from './improveError'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as cp from "child_process"; +import * as os from "os"; +import { isNumber } from "util"; +import * as vscode from "vscode"; +import { Event, EventEmitter } from "vscode"; +import { improveError } from "./improveError"; // We add these when we display to the output window -const stdInPrefix = '> '; -const stdErrPrefix = 'ERR> '; -const errorPrefix = 'Error running process: '; +const stdInPrefix = "> "; +const stdErrPrefix = "ERR> "; +const errorPrefix = "Error running process: "; const processStartupTimeout = 60; export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; + command: string; + args: string[]; + outputChannel?: vscode.OutputChannel; + workingDirectory?: string; + showTimeInOutputChannel?: boolean; + outputFilterSearch?: RegExp; + outputFilterReplace?: string; } export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create(options: IInteractiveChildProcessOptions): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess(options); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(' '); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false - }; - - this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); - this._childProc = cp.spawn(this._options.command, this._options.args, options); - - this._childProc.stdout?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on('error', (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on('close', (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel(text: string, displayPrefix?: string): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = (filteredText !== text && filteredText === ''); - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); - } - - return text; - } + private _childProc: cp.ChildProcess; + private readonly _options: IInteractiveChildProcessOptions; + private _startTime: number; + private _error: unknown; + private _isKilling: boolean; + + private readonly _onStdOutEmitter: EventEmitter = + new EventEmitter(); + private readonly _onStdErrEmitter: EventEmitter = + new EventEmitter(); + private readonly _onErrorEmitter: EventEmitter = + new EventEmitter(); + + private constructor(options: IInteractiveChildProcessOptions) { + this._options = options; + } + + public get onStdOut(): Event { + return this._onStdOutEmitter.event; + } + + public get onStdErr(): Event { + return this._onStdErrEmitter.event; + } + + public get onError(): Event { + return this._onErrorEmitter.event; + } + + public static async create( + options: IInteractiveChildProcessOptions + ): Promise { + const child: InteractiveChildProcess = new InteractiveChildProcess( + options + ); + await child.startCore(); + return child; + } + + public kill(): void { + this._isKilling = true; + this._childProc.kill(); + } + + public writeLine(text: string): void { + this.writeLineToOutputChannel(text, stdInPrefix); + this._childProc.stdin?.write(text + os.EOL); + } + + private async startCore(): Promise { + this._startTime = Date.now(); + const formattedArgs: string = this._options.args.join(" "); + + const workingDirectory = this._options.workingDirectory || os.tmpdir(); + const options: cp.SpawnOptions = { + cwd: workingDirectory, + + // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since + // the command is run in the shell, handling errors (such as command not found) would be more indirect, + // coming through STDERR instead of the error event + shell: false, + }; + + this.writeLineToOutputChannel( + `Starting executable: "${this._options.command}" ${formattedArgs}` + ); + this._childProc = cp.spawn( + this._options.command, + this._options.args, + options + ); + + this._childProc.stdout?.on("data", (data: string | Buffer) => { + const text = data.toString(); + this._onStdOutEmitter.fire(text); + this.writeLineToOutputChannel(text); + }); + + this._childProc.stderr?.on("data", (data: string | Buffer) => { + const text = data.toString(); + this._onStdErrEmitter.fire(text); + this.writeLineToOutputChannel(text, stdErrPrefix); + }); + + this._childProc.on("error", (error: unknown) => { + const improvedError = improveError(error); + this.setError(improvedError); + }); + + this._childProc.on("close", (code: number | null) => { + if (isNumber(code) && code !== 0) { + this.setError(`The process exited with code ${code}.`); + } else if (!this._isKilling) { + this.setError(`The process exited prematurely.`); + } + }); + + // Wait for the process to start up + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + await new Promise(async (resolve, reject) => { + const started = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + if (!!this._error || this._isKilling) { + reject(this._error); + break; + } else if (this._childProc.pid) { + resolve(); + break; + } else { + if (Date.now() > started + processStartupTimeout) { + reject("The process did not start in a timely manner"); + break; + } + await delay(50); + } + } + }); + } + + private writeLineToOutputChannel( + text: string, + displayPrefix?: string + ): void { + const filteredText = this.filterText(text); + const changedIntoEmptyString = + filteredText !== text && filteredText === ""; + + if (!changedIntoEmptyString) { + text = filteredText; + if (this._options.outputChannel) { + if (this._options.showTimeInOutputChannel) { + const ms = Date.now() - this._startTime; + text = `${ms}ms: ${text}`; + } + + text = (displayPrefix || "") + text; + this._options.outputChannel.appendLine(text); + } + } + } + + private setError(error: unknown): void { + this.writeLineToOutputChannel(parseError(error).message, errorPrefix); + this._error = this._error || error; + this._onErrorEmitter.fire(error); + } + + private filterText(text: string): string { + if (this._options.outputFilterSearch) { + return text.replace( + this._options.outputFilterSearch, + this._options.outputFilterReplace || "" + ); + } + + return text; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/utils/activityUtils.ts b/Source/utils/activityUtils.ts index fefd2fe00..d90c436cd 100644 --- a/Source/utils/activityUtils.ts +++ b/Source/utils/activityUtils.ts @@ -8,8 +8,13 @@ import { ext } from "../extensionVariables"; import { getWorkspaceSetting } from "./settingUtils"; export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), - }; + return { + registerActivity: async (activity) => + ext.rgApi.registerActivity(activity), + suppressNotification: await getWorkspaceSetting( + "suppressActivityNotifications", + undefined, + "azureResourceGroups" + ), + }; } diff --git a/Source/utils/array.ts b/Source/utils/array.ts index 06f095e8d..5d779a53a 100644 --- a/Source/utils/array.ts +++ b/Source/utils/array.ts @@ -4,11 +4,21 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { - return arr ? arr.filter(element => element instanceof genericConstructor) : []; +export function filterType( + arr: Object[] | undefined, + genericConstructor: new (...args: any[]) => T +): T[] { + return arr + ? arr.filter((element) => element instanceof genericConstructor) + : []; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { - return arr && arr.find(element => element instanceof genericConstructor); +export function findType( + arr: Object[] | undefined, + genericConstructor: new (...args: any[]) => T +): T | undefined { + return ( + arr && arr.find((element) => element instanceof genericConstructor) + ); } diff --git a/Source/utils/azureClients.ts b/Source/utils/azureClients.ts index 9be19e959..c2f44bd1c 100644 --- a/Source/utils/azureClients.ts +++ b/Source/utils/azureClients.ts @@ -3,22 +3,41 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; -import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { PostgreSQLManagementClient } from "@azure/arm-postgresql"; +import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; +import { + AzExtClientContext, + createAzureClient, +} from "@microsoft/vscode-azext-azureutils"; // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript -export async function createCosmosDBClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); +export async function createCosmosDBClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-cosmosdb")).CosmosDBManagementClient + ); } -export async function createPostgreSQLClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); +export async function createPostgreSQLClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-postgresql")).PostgreSQLManagementClient + ); } -export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); +export async function createPostgreSQLFlexibleClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-postgresql-flexible")) + .PostgreSQLManagementClient + ); } diff --git a/Source/utils/azureUtils.ts b/Source/utils/azureUtils.ts index b0017314b..0e067aa68 100644 --- a/Source/utils/azureUtils.ts +++ b/Source/utils/azureUtils.ts @@ -4,11 +4,13 @@ *--------------------------------------------------------------------------------------------*/ export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); + const matches: RegExpMatchArray | null = id.match( + /\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/ + ); - if (!matches || matches.length < 5) { - throw new Error('Invalid Azure Resource Id'); - } + if (!matches || matches.length < 5) { + throw new Error("Invalid Azure Resource Id"); + } - return matches[4]; + return matches[4]; } diff --git a/Source/utils/cp.ts b/Source/utils/cp.ts index 660dc3068..7f7d94117 100644 --- a/Source/utils/cp.ts +++ b/Source/utils/cp.ts @@ -3,12 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from 'child_process'; +import * as cp from "child_process"; -export async function commandSucceeds(command: string, ...args: string[]): Promise { - return await new Promise(resolve => { - cp.spawn(command, args) - .on('error', _error => resolve(false)) - .on('exit', code => resolve(code === 0)); - }); +export async function commandSucceeds( + command: string, + ...args: string[] +): Promise { + return await new Promise((resolve) => { + cp.spawn(command, args) + .on("error", (_error) => resolve(false)) + .on("exit", (code) => resolve(code === 0)); + }); } diff --git a/Source/utils/getIp.ts b/Source/utils/getIp.ts index 20d22e989..d3085ea52 100644 --- a/Source/utils/getIp.ts +++ b/Source/utils/getIp.ts @@ -1,61 +1,73 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { isIPv4 } from 'net'; -import { localize } from './localize'; - -export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { sendRequestWithTimeout } from "@microsoft/vscode-azext-azureutils"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { isIPv4 } from "net"; +import { localize } from "./localize"; + +export function isIpInRanges( + ip: string, + ranges: { startIpAddress: string; endIpAddress: string }[] +): boolean { + const ipNum = ipToNum(ip); + return ranges.some((range) => { + const startIpNum = ipToNum(range.startIpAddress); + const endIpNum = ipToNum(range.endIpAddress); + return startIpNum <= ipNum && ipNum <= endIpNum; + }); } export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, 'https://api.ipify.org/'), - () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; + const methods: (() => Promise)[] = [ + () => getPublicIpv4Https(context, "https://api.ipify.org/"), + () => getPublicIpv4Https(context, "https://ipv4.icanhazip.com/"), + ]; + + let lastError: unknown; + for (const getIp of methods) { + try { + return await getIp(); + } catch (e: unknown) { + lastError = e; + } + } + + throw lastError; } -const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); +const failedToGetIp = localize("failedToGetIp", "Failed to get public IP"); function ipToNum(ip: string) { - return Number( - ip.split(".") - .map(d => ("000" + d).substring(-3)) - .join("") - ); + return Number( + ip + .split(".") + .map((d) => ("000" + d).substring(-3)) + .join("") + ); } -async function getPublicIpv4Https(context: IActionContext, url: string): Promise { - const req = await sendRequestWithTimeout(context, { - method: 'GET', - url, - }, 5000, undefined); +async function getPublicIpv4Https( + context: IActionContext, + url: string +): Promise { + const req = await sendRequestWithTimeout( + context, + { + method: "GET", + url, + }, + 5000, + undefined + ); - const ip = req.bodyAsText; + const ip = req.bodyAsText; - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } + if (!ip || !isIPv4(ip)) { + throw new Error(failedToGetIp); + } - return ip; + return ip; } diff --git a/Source/utils/getSecretStorageKey.ts b/Source/utils/getSecretStorageKey.ts index 8e404f554..d04de6cea 100644 --- a/Source/utils/getSecretStorageKey.ts +++ b/Source/utils/getSecretStorageKey.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; + return `${serviceName}.${id}`; } diff --git a/Source/utils/improveError.ts b/Source/utils/improveError.ts index 27ff1f014..08f0bedaf 100644 --- a/Source/utils/improveError.ts +++ b/Source/utils/improveError.ts @@ -6,12 +6,12 @@ import { parseError } from "@microsoft/vscode-azext-utils"; export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } + const message = parseError(error).message; + // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" + const match = message.match(/spawn (.*) ENOENT/); + if (match) { + return new Error(`Could not find ${match[1]}`); + } - return error; + return error; } diff --git a/Source/utils/localize.ts b/Source/utils/localize.ts index 2aee3fa12..76d8fbf4d 100644 --- a/Source/utils/localize.ts +++ b/Source/utils/localize.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vscode-nls'; +import * as nls from "vscode-nls"; export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Source/utils/nonNull.ts b/Source/utils/nonNull.ts index d7104b4f8..e9437afc9 100644 --- a/Source/utils/nonNull.ts +++ b/Source/utils/nonNull.ts @@ -3,39 +3,52 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { isNullOrUndefined } from 'util'; +import { isNullOrUndefined } from "util"; /** * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed * for the property and will give a compile error if the given name is not a property of the source. */ -export function nonNullProp(source: TSource, name: TKey): NonNullable { - const value: NonNullable = >source[name]; - return nonNullValue(value, name); +export function nonNullProp( + source: TSource, + name: TKey +): NonNullable { + const value: NonNullable = >( + source[name] + ); + return nonNullValue(value, name); } /** * Validates that a given value is not null and not undefined. */ -export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { - if (isNullOrUndefined(value)) { - throw new Error( - 'Internal error: Expected value to be neither null nor undefined' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } +export function nonNullValue( + value: T | undefined | null, + propertyNameOrMessage?: string +): T { + if (isNullOrUndefined(value)) { + throw new Error( + "Internal error: Expected value to be neither null nor undefined" + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") + ); + } - return value; + return value; } /** * Validates that a given string is not null, undefined, nor empty */ -export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { - if (!value) { - throw new Error( - 'Internal error: Expected value to be neither null, undefined, nor empty' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } +export function nonNullOrEmptyValue( + value: string | undefined, + propertyNameOrMessage?: string +): string { + if (!value) { + throw new Error( + "Internal error: Expected value to be neither null, undefined, nor empty" + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") + ); + } - return value; + return value; } diff --git a/Source/utils/openUrl.ts b/Source/utils/openUrl.ts index 0be3f5bbb..5c7deaca7 100644 --- a/Source/utils/openUrl.ts +++ b/Source/utils/openUrl.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as open from 'open'; +import * as open from "open"; export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); + // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 + // await vscode.env.openExternal(vscode.Uri.parse(url)); - await open(url); + await open(url); } diff --git a/Source/utils/randomUtils.ts b/Source/utils/randomUtils.ts index 7a313f23a..1c4856b09 100644 --- a/Source/utils/randomUtils.ts +++ b/Source/utils/randomUtils.ts @@ -6,12 +6,15 @@ import * as crypto from "crypto"; export namespace randomUtils { - export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { - return crypto.createHash('sha256').update(s).digest(encoding); - } + export function getPseudononymousStringHash( + s: string, + encoding: crypto.BinaryToTextEncoding = "base64" + ): string { + return crypto.createHash("sha256").update(s).digest(encoding); + } - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString('hex').slice(0, length); - } + export function getRandomHexString(length: number): string { + const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); + return buffer.toString("hex").slice(0, length); + } } diff --git a/Source/utils/settingUtils.ts b/Source/utils/settingUtils.ts index 0ac1004c2..0f75feb17 100644 --- a/Source/utils/settingUtils.ts +++ b/Source/utils/settingUtils.ts @@ -3,60 +3,98 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; +import { + ConfigurationTarget, + Uri, + workspace, + WorkspaceConfiguration, +} from "vscode"; import { ext } from "../extensionVariables"; /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - await projectConfiguration.update(section, value, ConfigurationTarget.Global); +export async function updateGlobalSetting( + section: string, + value: T, + prefix: string = ext.prefix +): Promise { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix); + await projectConfiguration.update( + section, + value, + ConfigurationTarget.Global + ); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); +export async function updateWorkspaceSetting( + section: string, + value: T, + fsPath: string, + prefix: string = ext.prefix +): Promise { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix, Uri.file(fsPath)); + await projectConfiguration.update(section, value); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); - return result && result.globalValue; +export function getGlobalSetting( + key: string, + prefix: string = ext.prefix +): T | undefined { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix); + const result: { globalValue?: T } | undefined = + projectConfiguration.inspect(key); + return result && result.globalValue; } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); - return projectConfiguration.get(key); +export function getWorkspaceSetting( + key: string, + fsPath?: string, + prefix: string = ext.prefix +): T | undefined { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration( + prefix, + fsPath ? Uri.file(fsPath) : undefined + ); + return projectConfiguration.get(key); } /** * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } +export function getWorkspaceSettingFromAnyFolder( + key: string, + prefix: string = ext.prefix +): string | undefined { + if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { + let result: string | undefined; + for (const folder of workspace.workspaceFolders) { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix, folder.uri); + const folderResult: string | undefined = + projectConfiguration.get(key); + if (!result) { + result = folderResult; + } else if (folderResult && result !== folderResult) { + return undefined; + } + } + return result; + } else { + return getGlobalSetting(key, prefix); + } } diff --git a/Source/utils/timeout.ts b/Source/utils/timeout.ts index cc5ffb2d6..1645f6d3f 100644 --- a/Source/utils/timeout.ts +++ b/Source/utils/timeout.ts @@ -8,44 +8,50 @@ const timedOutMessage = "Execution timed out"; /** * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. */ -export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } +export async function valueOnTimeout( + timeoutMs: number, + timeoutValue: T, + action: () => Promise | T +): Promise { + try { + return await rejectOnTimeout(timeoutMs, action); + } catch (err) { + const error = <{ message?: string }>err; + if (error && error.message === timedOutMessage) { + return timeoutValue; + } - throw err; - } + throw err; + } } /** * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. */ -export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout( - () => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, - timeoutMs); +export async function rejectOnTimeout( + timeoutMs: number, + action: () => Promise | T, + callerTimeOutMessage?: string +): Promise { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + return await new Promise(async (resolve, reject) => { + let timer: NodeJS.Timer | undefined = setTimeout(() => { + timer = undefined; + reject(new Error(callerTimeOutMessage || timedOutMessage)); + }, timeoutMs); - let value: T; - let error; + let value: T; + let error; - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); + try { + value = await action(); + clearTimeout(timer); + resolve(value); + } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + error = err; + clearTimeout(timer); + reject(error); + } + }); } diff --git a/Source/utils/vscodeUtils.ts b/Source/utils/vscodeUtils.ts index d05f84872..bdb5665b5 100644 --- a/Source/utils/vscodeUtils.ts +++ b/Source/utils/vscodeUtils.ts @@ -3,101 +3,145 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from '@azure/cosmos'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; -import { getRootPath } from './workspacUtils'; +import { ItemDefinition } from "@azure/cosmos"; +import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import * as path from "path"; +import * as vscode from "vscode"; +import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../extensionVariables"; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { IMongoDocument } from "../mongo/tree/MongoDocumentTreeItem"; +import { getRootPath } from "./workspacUtils"; export interface IDisposable { - dispose(): void; + dispose(): void; } export function dispose(disposables: T[]): T[] { - disposables.forEach(d => d.dispose()); - return []; + disposables.forEach((d) => d.dispose()); + return []; } export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; + return { dispose }; } -export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); - const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); - await writeToEditor(editor, data); +export async function showNewFile( + data: string, + fileName: string, + fileExtension: string, + column?: vscode.ViewColumn +): Promise { + const folderPath: string = getRootPath() || ext.context.extensionPath; + const fullFileName: string | undefined = await getUniqueFileName( + folderPath, + fileName, + fileExtension + ); + const uri: vscode.Uri = vscode.Uri.file( + path.join(folderPath, fullFileName) + ).with({ scheme: "untitled" }); + const textDocument = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument( + textDocument, + column + ? column > vscode.ViewColumn.Three + ? vscode.ViewColumn.One + : column + : undefined, + true + ); + await writeToEditor(editor, data); } -export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt(editor.document.lineCount - 1); - editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); - } +export async function writeToEditor( + editor: vscode.TextEditor, + data: string +): Promise { + await editor.edit((editBuilder: vscode.TextEditorEdit) => { + if (editor.document.lineCount > 0) { + const lastLine = editor.document.lineAt( + editor.document.lineCount - 1 + ); + editBuilder.delete( + new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position( + lastLine.range.start.line, + lastLine.range.end.character + ) + ) + ); + } - editBuilder.insert(new vscode.Position(0, 0), data); - }); + editBuilder.insert(new vscode.Position(0, 0), data); + }); } -async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { - let count: number = 1; - const maxCount: number = 1024; +async function getUniqueFileName( + folderPath: string, + fileName: string, + fileExtension: string +): Promise { + let count: number = 1; + const maxCount: number = 1024; - while (count < maxCount) { - const fileSuffix = count === 0 ? '' : '-' + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; + while (count < maxCount) { + const fileSuffix = count === 0 ? "" : "-" + count.toString(); + const fullFileName: string = fileName + fileSuffix + fileExtension; - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } + const fullPath: string = path.join(folderPath, fullFileName); + const pathExists: boolean = await fse.pathExists(fullPath); + const editorExists: boolean = + vscode.workspace.textDocuments.find( + (doc) => doc.uri.fsPath === fullPath + ) !== undefined; + if (!pathExists && !editorExists) { + return fullFileName; + } + count += 1; + } - throw new Error('Could not find unique name for new file.'); + throw new Error("Could not find unique name for new file."); } export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join('/'); + const labels = [node.label]; + while (node.parent) { + node = node.parent; + labels.unshift(node.label); + if (isAccountTreeItem(node)) { + break; + } + } + return labels.join("/"); } function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); + return ( + treeItem instanceof MongoAccountTreeItem || + treeItem instanceof DocDBAccountTreeItemBase + ); } -export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== 'object') { - return String(value); - } - } - } - return String(document._id); +export function getDocumentTreeItemLabel( + document: IMongoDocument | ItemDefinition +): string { + for (const field of getDocumentLabelFields()) { + // eslint-disable-next-line no-prototype-builtins + if (document.hasOwnProperty(field)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const value = document[field]; + if (value !== undefined && typeof value !== "object") { + return String(value); + } + } + } + return String(document._id); } function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; + const settingKey: string = ext.settingsKeys.documentLabelFields; + return vscode.workspace.getConfiguration().get(settingKey) || []; } diff --git a/Source/utils/workspacUtils.ts b/Source/utils/workspacUtils.ts index 20b60da11..6892c2f6d 100644 --- a/Source/utils/workspacUtils.ts +++ b/Source/utils/workspacUtils.ts @@ -3,16 +3,23 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { nonNullValue } from './nonNull'; +import * as vscode from "vscode"; +import { ext } from "../extensionVariables"; +import { nonNullValue } from "./nonNull"; export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; + // if this is a multi-root workspace, return undefined + return vscode.workspace.workspaceFolders && + vscode.workspace.workspaceFolders.length === 1 + ? vscode.workspace.workspaceFolders[0].uri.fsPath + : undefined; } export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); + const config: vscode.WorkspaceConfiguration = + vscode.workspace.getConfiguration(); + return nonNullValue( + config.get(ext.settingsKeys.batchSize), + "batchSize" + ); } diff --git a/Source/utils/wrapError.ts b/Source/utils/wrapError.ts index f6ec5d2b5..b82f638fd 100644 --- a/Source/utils/wrapError.ts +++ b/Source/utils/wrapError.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; +import * as os from "os"; export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } + if (!innerError) { + return outerError; + } else if (!outerError) { + return innerError; + } - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } + const innerMessage = parseError(innerError).message; + const outerMessage = parseError(outerError).message; + if (outerError instanceof Error) { + outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; + return outerError; + } - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); + return new Error(`${outerMessage}${os.EOL}${innerMessage}`); } diff --git a/Source/vscode-cosmosdb.api.d.ts b/Source/vscode-cosmosdb.api.d.ts index d5e4416c1..4e813c5e5 100644 --- a/Source/vscode-cosmosdb.api.d.ts +++ b/Source/vscode-cosmosdb.api.d.ts @@ -4,93 +4,103 @@ *--------------------------------------------------------------------------------------------*/ export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem(query: TreeItemQuery): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; + apiVersion: string; + + /** + * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. + * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. + * + * @param query The query object to use for the find + */ + findTreeItem( + query: TreeItemQuery + ): Promise; + + /** + * Prompts the user to pick an item from the Azure Databases tree + * + * @param options Configures the behavior of the tree item picker + */ + pickTreeItem( + options: PickTreeItemOptions & { resourceType: "DatabaseAccount" } + ): Promise; + pickTreeItem( + options: PickTreeItemOptions & { resourceType: "Database" } + ): Promise; + + /** + * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string + */ + revealTreeItem(resourceId: string): Promise; } export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; + /** + * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. + */ + reveal(): Promise; } export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - } - - docDBData?: { - masterKey: string; - documentEndpoint: string; - } - - postgresData?: { - username: string | undefined; - password: string | undefined; - } - + hostName: string; + port: string; + connectionString: string; + + /** + * Data specific to Azure or undefined if the resource is not in Azure. + */ + azureData?: { + accountName: string; + accountId: string; + }; + + docDBData?: { + masterKey: string; + documentEndpoint: string; + }; + + postgresData?: { + username: string | undefined; + password: string | undefined; + }; } export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; + databaseName: string; } -export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; +export type AzureDatabasesResourceType = "DatabaseAccount" | "Database"; -export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; +export type AzureDatabasesApiType = + | "Mongo" + | "SQL" + | "Graph" + | "Table" + | "Postgres"; export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; + /** + * The resource type of the picked item + */ + resourceType: AzureDatabasesResourceType; + + /** + * An array of the API types that can be picked, or undefined if all API types are allowed + */ + apiType?: AzureDatabasesApiType[]; } export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - } + /** + * An account or database connection string + */ + connectionString?: string; + + postgresData?: { + hostName: string; + port: string; + databaseName: string | undefined; + username: string | undefined; + password: string | undefined; + }; } diff --git a/Source/vscode-cosmosdbgraph.api.d.ts b/Source/vscode-cosmosdbgraph.api.d.ts index 95cde2531..bf8d4c769 100644 --- a/Source/vscode-cosmosdbgraph.api.d.ts +++ b/Source/vscode-cosmosdbgraph.api.d.ts @@ -4,26 +4,26 @@ *--------------------------------------------------------------------------------------------*/ export interface CosmosDBGraphExtensionApi { - apiVersion: string; + apiVersion: string; - openGraphExplorer(config: IGraphConfiguration): Promise; + openGraphExplorer(config: IGraphConfiguration): Promise; } export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; + host: string; + port: number; + ssl: boolean; } export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; + // e.g. https://graphaccount.documents.azure.com:443 + documentEndpoint: string; - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; + gremlinEndpoint?: IGremlinEndpoint; + possibleGremlinEndpoints: IGremlinEndpoint[]; - key: string; - databaseName: string; - graphName: string; - tabTitle: string; + key: string; + databaseName: string; + graphName: string; + tabTitle: string; } diff --git a/build/vscode-languageserver-files-stub.js b/build/vscode-languageserver-files-stub.js index b7e70019f..568f06348 100644 --- a/build/vscode-languageserver-files-stub.js +++ b/build/vscode-languageserver-files-stub.js @@ -10,7 +10,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const url = require("url"); const path = require("path"); @@ -21,25 +21,25 @@ const child_process_1 = require("child_process"); * complete implementation of handling VS Code URIs. */ function uriToFilePath(uri) { - let parsed = url.parse(uri); - if (parsed.protocol !== 'file:' || !parsed.path) { - return undefined; - } - let segments = parsed.path.split('/'); - for (var i = 0, len = segments.length; i < len; i++) { - segments[i] = decodeURIComponent(segments[i]); - } - if (process.platform === 'win32' && segments.length > 1) { - let first = segments[0]; - let second = segments[1]; - // Do we have a drive letter and we started with a / which is the - // case if the first segement is empty (see split above) - if (first.length === 0 && second.length > 1 && second[1] === ':') { - // Remove first slash - segments.shift(); - } - } - return path.normalize(segments.join('/')); + let parsed = url.parse(uri); + if (parsed.protocol !== "file:" || !parsed.path) { + return undefined; + } + let segments = parsed.path.split("/"); + for (var i = 0, len = segments.length; i < len; i++) { + segments[i] = decodeURIComponent(segments[i]); + } + if (process.platform === "win32" && segments.length > 1) { + let first = segments[0]; + let second = segments[1]; + // Do we have a drive letter and we started with a / which is the + // case if the first segement is empty (see split above) + if (first.length === 0 && second.length > 1 && second[1] === ":") { + // Remove first slash + segments.shift(); + } + } + return path.normalize(segments.join("/")); } exports.uriToFilePath = uriToFilePath; @@ -47,26 +47,26 @@ exports.uriToFilePath = uriToFilePath; // Throw NYI if any of the other functions are ever called (they shouldn't be currently) function resolveModule(workspaceRoot, moduleName) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModule = resolveModule; function resolve(moduleName, nodePath, cwd, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolve = resolve; function resolveGlobalNodePath(tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveGlobalNodePath = resolveGlobalNodePath; function resolveGlobalYarnPath(tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveGlobalYarnPath = resolveGlobalYarnPath; function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModulePath = resolveModulePath; function resolveModule2(workspaceRoot, moduleName, nodePath, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModule2 = resolveModule2; diff --git a/extension.bundle.ts b/extension.bundle.ts index 0cd4aff0d..aef525815 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -12,38 +12,66 @@ // Export activate/deactivate for main.js // The tests use instanceof against these and therefore we need to make sure we're using the same version of the bson module in the tests as in the bundle, // so export it from the bundle itself. -export { ObjectID, ObjectId } from 'bson'; +export { ObjectID, ObjectId } from "bson"; // Exports for tests // The tests are not packaged with the webpack bundle and therefore only have access to code exported from this file. // // The tests should import '../extension.bundle.ts'. At design-time they live in tests/ and so will pick up this file (extension.bundle.ts). // At runtime the tests live in dist/tests and will therefore pick up the main webpack bundle at dist/extension.bundle.js. -export { AzureAccountTreeItemBase, createAzureClient } from '@microsoft/vscode-azext-azureutils'; -export * from '@microsoft/vscode-azext-utils'; -export { emulatorPassword, isWindows } from './src/constants'; -export { ParsedDocDBConnectionString, parseDocDBConnectionString } from './src/docdb/docDBConnectionStrings'; -export { getCosmosClient } from './src/docdb/getCosmosClient'; -export * from './src/docdb/registerDocDBCommands'; -export { activateInternal, cosmosDBCopyConnectionString, createServer, deactivateInternal, deleteAccount } from './src/extension'; -export { ext } from './src/extensionVariables'; -export * from './src/graph/registerGraphCommands'; -export { connectToMongoClient, isCosmosEmulatorConnectionString } from './src/mongo/connectToMongoClient'; -export { MongoCommand } from './src/mongo/MongoCommand'; -export { addDatabaseToAccountConnectionString, encodeMongoConnectionString, getDatabaseNameFromConnectionString } from './src/mongo/mongoConnectionStrings'; -export { findCommandAtPosition, getAllCommandsFromText } from './src/mongo/MongoScrapbook'; -export { MongoShell } from './src/mongo/MongoShell'; -export * from './src/mongo/registerMongoCommands'; -export { IDatabaseInfo } from './src/mongo/tree/MongoAccountTreeItem'; -export { addDatabaseToConnectionString } from './src/postgres/postgresConnectionStrings'; -export { AttachedAccountsTreeItem, MONGO_CONNECTION_EXPECTED } from './src/tree/AttachedAccountsTreeItem'; -export { AzureAccountTreeItemWithAttached } from './src/tree/AzureAccountTreeItemWithAttached'; -export * from './src/utils/azureClients'; -export { improveError } from './src/utils/improveError'; -export { randomUtils } from './src/utils/randomUtils'; -export { getGlobalSetting, updateGlobalSetting } from './src/utils/settingUtils'; -export { rejectOnTimeout, valueOnTimeout } from './src/utils/timeout'; -export { getDocumentTreeItemLabel, IDisposable } from './src/utils/vscodeUtils'; -export { wrapError } from './src/utils/wrapError'; -export { isIpInRanges, getPublicIpv4 } from './src/utils/getIp' +export { + AzureAccountTreeItemBase, + createAzureClient, +} from "@microsoft/vscode-azext-azureutils"; +export * from "@microsoft/vscode-azext-utils"; +export { emulatorPassword, isWindows } from "./src/constants"; +export { + ParsedDocDBConnectionString, + parseDocDBConnectionString, +} from "./src/docdb/docDBConnectionStrings"; +export { getCosmosClient } from "./src/docdb/getCosmosClient"; +export * from "./src/docdb/registerDocDBCommands"; +export { + activateInternal, + cosmosDBCopyConnectionString, + createServer, + deactivateInternal, + deleteAccount, +} from "./src/extension"; +export { ext } from "./src/extensionVariables"; +export * from "./src/graph/registerGraphCommands"; +export { + connectToMongoClient, + isCosmosEmulatorConnectionString, +} from "./src/mongo/connectToMongoClient"; +export { MongoCommand } from "./src/mongo/MongoCommand"; +export { + addDatabaseToAccountConnectionString, + encodeMongoConnectionString, + getDatabaseNameFromConnectionString, +} from "./src/mongo/mongoConnectionStrings"; +export { + findCommandAtPosition, + getAllCommandsFromText, +} from "./src/mongo/MongoScrapbook"; +export { MongoShell } from "./src/mongo/MongoShell"; +export * from "./src/mongo/registerMongoCommands"; +export { IDatabaseInfo } from "./src/mongo/tree/MongoAccountTreeItem"; +export { addDatabaseToConnectionString } from "./src/postgres/postgresConnectionStrings"; +export { + AttachedAccountsTreeItem, + MONGO_CONNECTION_EXPECTED, +} from "./src/tree/AttachedAccountsTreeItem"; +export { AzureAccountTreeItemWithAttached } from "./src/tree/AzureAccountTreeItemWithAttached"; +export * from "./src/utils/azureClients"; +export { improveError } from "./src/utils/improveError"; +export { randomUtils } from "./src/utils/randomUtils"; +export { + getGlobalSetting, + updateGlobalSetting, +} from "./src/utils/settingUtils"; +export { rejectOnTimeout, valueOnTimeout } from "./src/utils/timeout"; +export { getDocumentTreeItemLabel, IDisposable } from "./src/utils/vscodeUtils"; +export { wrapError } from "./src/utils/wrapError"; +export { isIpInRanges, getPublicIpv4 } from "./src/utils/getIp"; // NOTE: The auto-fix action "source.organizeImports" does weird things with this file, but there doesn't seem to be a way to disable it on a per-file basis so we'll just let it happen diff --git a/grammar/JavaScript.tmLanguage.json b/grammar/JavaScript.tmLanguage.json index 71207a7b3..4928616c4 100644 --- a/grammar/JavaScript.tmLanguage.json +++ b/grammar/JavaScript.tmLanguage.json @@ -1,3713 +1,3711 @@ { - "name.$comment": "** Changed **", - "name": "Mongo Scrapbooks (JavaScript)", - "scopeName.$comment": "** Changed **", - "scopeName": "source.mongo.js", - "fileTypes.$comment": "** Changed from .js/.jsx **", - "fileTypes": [ - ".mongo" - ], - "uuid.$comment": "** Changed **", - "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", - "patterns": [ - { - "include": "#directives" - }, - { - "include": "#statements" - }, - { - "name": "comment.line.shebang.ts", - "match": "\\A(#!).*(?=$)", - "captures": { - "1": { - "name": "punctuation.definition.comment.ts" - } - } - } - ], - "repository": { - "statements": { - "patterns": [ - { - "include": "#string" - }, - { - "include": "#template" - }, - { - "include": "#comment" - }, - { - "include": "#declaration" - }, - { - "include": "#switch-statement" - }, - { - "include": "#for-loop" - }, - { - "include": "#after-operator-block" - }, - { - "include": "#decl-block" - }, - { - "include": "#control-statement" - }, - { - "include": "#expression" - }, - { - "include": "#punctuation-semicolon" - } - ] - }, - "var-expr": { - "name": "meta.var.expr.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js entity.name.function.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.constant.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.readwrite.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - } - ] - }, - "var-single-variable-type-annotation": { - "patterns": [ - { - "include": "#type-annotation" - }, - { - "include": "#string" - }, - { - "include": "#comment" - } - ] - }, - "destructuring-variable": { - "patterns": [ - { - "name": "meta.object-binding-pattern-variable.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" - }, - { - "name": "meta.definition.property.js variable.object.property.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.js", - "match": "\\?" - } - ] - } - ] - }, - "method-declaration": { - "name": "meta.method.declaration.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "captures": { - "1": { - "name": "storage.modifier.js" - }, - "2": { - "name": "keyword.operator.rest.js" - }, - "3": { - "name": "entity.name.function.js" - }, - "4": { - "name": "keyword.operator.optional.js" - } - } - }, - { - "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type" - } - ] - }, - "type": { - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#string" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#type-primitive" - }, - { - "include": "#type-builtin-literals" - }, - { - "include": "#type-parameters" - }, - { - "include": "#type-tuple" - }, - { - "include": "#type-object" - }, - { - "include": "#type-operators" - }, - { - "include": "#type-fn-type-parameters" - }, - { - "include": "#type-paren-or-function-parameters" - }, - { - "include": "#type-function-return-type" - }, - { - "include": "#type-name" - } - ] - }, - "function-parameters": { - "name": "meta.parameters.js", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#decorator" - }, - { - "include": "#destructuring-parameter" - }, - { - "include": "#parameter-name" - }, - { - "include": "#type-annotation" - }, - { - "include": "#variable-initializer" - }, - { - "name": "punctuation.separator.parameter.js", - "match": "," - } - ] - }, - "type-primitive": { - "name": "support.type.primitive.js", - "match": "(?)\n ))\n )\n )\n)", - "end": "(?<=\\))", - "patterns": [ - { - "include": "#function-parameters" - } - ] - } - ] - }, - "type-operators": { - "patterns": [ - { - "include": "#typeof-operator" - }, - { - "name": "keyword.operator.type.js", - "match": "[&|]" - }, - { - "name": "keyword.operator.expression.keyof.js", - "match": "(?", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", - "patterns": [ - { - "include": "#comment" - }, - { - "name": "meta.object.type.js", - "begin": "(?<==>)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "type-tuple": { - "name": "meta.type.tuple.js", - "begin": "\\[", - "beginCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "type-name": { - "patterns": [ - { - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", - "captures": { - "1": { - "name": "entity.name.type.module.js" - }, - "2": { - "name": "punctuation.accessor.js" - } - } - }, - { - "name": "entity.name.type.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "type-parameters": { - "name": "meta.type.parameters.js", - "begin": "(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "(?=$)|(>)", - "endCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "name": "storage.modifier.js", - "match": "(?)" - }, - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "variable-initializer": { - "patterns": [ - { - "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "support.constant.dom.js" - }, - "3": { - "name": "support.variable.property.dom.js" - } - } - }, - { - "name": "support.class.node.js", - "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", - "patterns": [ - { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "entity.name.function.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - }, - { - "include": "#comment" - }, - { - "name": "meta.type.parameters.js", - "begin": "\\<", - "beginCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "\\>", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - { - "include": "#paren-expression" - } - ] - }, - "identifiers": { - "patterns": [ - { - "include": "#object-identifiers" - }, - { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "entity.name.function.js" - } - } - }, - { - "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.property.js" - } - } - }, - { - "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.property.js" - } - } - }, - { - "name": "variable.other.constant.js", - "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" - }, - { - "name": "variable.other.readwrite.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "object-identifiers": { - "patterns": [ - { - "name": "support.class.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" - }, - { - "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.object.property.js" - }, - "3": { - "name": "variable.other.object.property.js" - } - } - }, - { - "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "variable.other.constant.object.js" - }, - "2": { - "name": "variable.other.object.js" - } - } - } - ] - }, - "cast": { - "patterns": [ - { - "include": "#jsx" - } - ] - }, - "new-expr": { - "name": "new.expr.js", - "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "entity.name.function.js" - }, - "2": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "\\.\\.\\.", - "beginCaptures": { - "0": { - "name": "keyword.operator.spread.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", - "captures": { - "1": { - "name": "variable.other.readwrite.js" - } - } - }, - { - "include": "#punctuation-comma" - } - ] - }, - "expression-operators": { - "patterns": [ - { - "name": "keyword.control.flow.js", - "match": "(?>=|>>>=|\\|=" - }, - { - "name": "keyword.operator.bitwise.shift.js", - "match": "<<|>>>|>>" - }, - { - "name": "keyword.operator.comparison.js", - "match": "===|!==|==|!=" - }, - { - "name": "keyword.operator.relational.js", - "match": "<=|>=|<>|<|>" - }, - { - "name": "keyword.operator.logical.js", - "match": "\\!|&&|\\|\\|" - }, - { - "name": "keyword.operator.bitwise.js", - "match": "\\&|~|\\^|\\|" - }, - { - "name": "keyword.operator.assignment.js", - "match": "\\=" - }, - { - "name": "keyword.operator.decrement.js", - "match": "--" - }, - { - "name": "keyword.operator.increment.js", - "match": "\\+\\+" - }, - { - "name": "keyword.operator.arithmetic.js", - "match": "%|\\*|/|-|\\+" - }, - { - "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", - "captures": { - "1": { - "name": "keyword.operator.arithmetic.js" - } - } - } - ] - }, - "typeof-operator": { - "name": "keyword.operator.expression.typeof.js", - "match": "(?)", - "captures": { - "1": { - "name": "storage.modifier.async.js" - }, - "2": { - "name": "variable.parameter.js" - } - } - }, - { - "name": "meta.arrow.js", - "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type-parameters" - }, - { - "include": "#function-parameters" - }, - { - "include": "#arrow-return-type" - } - ] - }, - { - "name": "meta.arrow.js", - "begin": "=>", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?<=\\})|((?!\\{)(?=\\S))", - "patterns": [ - { - "include": "#decl-block" - }, - { - "include": "#expression" - } - ] - } - ] - }, - "arrow-return-type": { - "name": "meta.return.type.arrow.js", - "begin": "(?<=\\))\\s*(:)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "name": "meta.object.type.js", - "begin": "(?<=:)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "punctuation-comma": { - "name": "punctuation.separator.comma.js", - "match": "," - }, - "punctuation-semicolon": { - "name": "punctuation.terminator.statement.js", - "match": ";" - }, - "punctuation-accessor": { - "name": "punctuation.accessor.js", - "match": "\\." - }, - "paren-expression": { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "patterns": [ - { - "include": "#expression" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "qstring-double": { - "name": "string.quoted.double.js", - "begin": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\")|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "qstring-single": { - "name": "string.quoted.single.js", - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\\')|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "regex": { - "patterns": [ - { - "name": "string.regexp.js", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(/)([gimuy]*)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "keyword.other.js" - } - }, - "patterns": [ - { - "include": "#regexp" - } - ] - }, - { - "name": "string.regexp.js", - "begin": "(?\\s*$)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.js" - } - }, - "end": "(?=$)", - "patterns": [ - { - "name": "meta.tag.js", - "begin": "(<)(reference|amd-dependency|amd-module)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.directive.js" - }, - "2": { - "name": "entity.name.tag.directive.js" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.directive.js" - } - }, - "patterns": [ - { - "name": "entity.other.attribute-name.directive.js", - "match": "path|types|no-default-lib|name" - }, - { - "name": "keyword.operator.assignment.js", - "match": "=" - }, - { - "include": "#string" - } - ] - } - ] - }, - "docblock": { - "patterns": [ - { - "name": "storage.type.class.jsdoc", - "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "variable.other.jsdoc" - }, - "3": { - "name": "other.description.jsdoc" - } - } - }, - { - "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "other.description.jsdoc" - } - } - } - ] - }, - "jsx-tag-attributes": { - "patterns": [ - { - "include": "#jsx-tag-attribute-name" - }, - { - "include": "#jsx-tag-attribute-assignment" - }, - { - "include": "#jsx-string-double-quoted" - }, - { - "include": "#jsx-string-single-quoted" - }, - { - "include": "#jsx-evaluated-code" - } - ] - }, - "jsx-tag-attribute-name": { - "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", - "captures": { - "1": { - "name": "entity.other.attribute-name.js" - } - } - }, - "jsx-tag-attribute-assignment": { - "name": "keyword.operator.assignment.js", - "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" - }, - "jsx-string-double-quoted": { - "name": "string.quoted.double.js", - "begin": "\"", - "end": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-string-single-quoted": { - "name": "string.quoted.single.js", - "begin": "'", - "end": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-entities": { - "patterns": [ - { - "name": "constant.character.entity.js", - "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", - "captures": { - "1": { - "name": "punctuation.definition.entity.js" - }, - "3": { - "name": "punctuation.definition.entity.js" - } - } - }, - { - "name": "invalid.illegal.bad-ampersand.js", - "match": "&" - } - ] - }, - "jsx-evaluated-code": { - "name": "meta.embedded.expression.js", - "begin": "\\{", - "end": "\\}", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.js" - } - }, - "patterns": [ - { - "include": "#expression" - } - ] - }, - "jsx-tag-attributes-illegal": { - "name": "invalid.illegal.attribute.js", - "match": "\\S+" - }, - "jsx-tag-without-attributes": { - "name": "meta.tag.without-attributes.js", - "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", - "end": "()", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "endCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "contentName": "meta.jsx.children.tsx", - "patterns": [ - { - "include": "#jsx-children" - } - ] - }, - "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-child-tag": { - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-tag": { - "name": "meta.tag.js", - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(?=(/>)|(?:()))", - "patterns": [ - { - "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - } - }, - "end": "(?=[/]?>)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#jsx-tag-attributes" - }, - { - "include": "#jsx-tag-attributes-illegal" - } - ] - }, - { - "begin": "(>)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.end.js" - } - }, - "end": "(?=" - }, - "jsx-children": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-child-tag" - }, - { - "include": "#jsx-tag-invalid" - }, - { - "include": "#jsx-evaluated-code" - }, - { - "include": "#jsx-entities" - } - ] - }, - "jsx": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-tag-in-expression" - }, - { - "include": "#jsx-tag-invalid" - } - ] - } - }, - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" + "name.$comment": "** Changed **", + "name": "Mongo Scrapbooks (JavaScript)", + "scopeName.$comment": "** Changed **", + "scopeName": "source.mongo.js", + "fileTypes.$comment": "** Changed from .js/.jsx **", + "fileTypes": [".mongo"], + "uuid.$comment": "** Changed **", + "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", + "patterns": [ + { + "include": "#directives" + }, + { + "include": "#statements" + }, + { + "name": "comment.line.shebang.ts", + "match": "\\A(#!).*(?=$)", + "captures": { + "1": { + "name": "punctuation.definition.comment.ts" + } + } + } + ], + "repository": { + "statements": { + "patterns": [ + { + "include": "#string" + }, + { + "include": "#template" + }, + { + "include": "#comment" + }, + { + "include": "#declaration" + }, + { + "include": "#switch-statement" + }, + { + "include": "#for-loop" + }, + { + "include": "#after-operator-block" + }, + { + "include": "#decl-block" + }, + { + "include": "#control-statement" + }, + { + "include": "#expression" + }, + { + "include": "#punctuation-semicolon" + } + ] + }, + "var-expr": { + "name": "meta.var.expr.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js entity.name.function.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + }, + { + "name": "meta.var-single-variable.expr.js", + "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js variable.other.constant.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + }, + { + "name": "meta.var-single-variable.expr.js", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js variable.other.readwrite.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + } + ] + }, + "var-single-variable-type-annotation": { + "patterns": [ + { + "include": "#type-annotation" + }, + { + "include": "#string" + }, + { + "include": "#comment" + } + ] + }, + "destructuring-variable": { + "patterns": [ + { + "name": "meta.object-binding-pattern-variable.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" + }, + { + "name": "meta.definition.property.js variable.object.property.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.js", + "match": "\\?" + } + ] + } + ] + }, + "method-declaration": { + "name": "meta.method.declaration.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", + "captures": { + "1": { + "name": "storage.modifier.js" + }, + "2": { + "name": "keyword.operator.rest.js" + }, + "3": { + "name": "entity.name.function.js" + }, + "4": { + "name": "keyword.operator.optional.js" + } + } + }, + { + "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type" + } + ] + }, + "type": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#string" + }, + { + "include": "#numeric-literal" + }, + { + "include": "#type-primitive" + }, + { + "include": "#type-builtin-literals" + }, + { + "include": "#type-parameters" + }, + { + "include": "#type-tuple" + }, + { + "include": "#type-object" + }, + { + "include": "#type-operators" + }, + { + "include": "#type-fn-type-parameters" + }, + { + "include": "#type-paren-or-function-parameters" + }, + { + "include": "#type-function-return-type" + }, + { + "include": "#type-name" + } + ] + }, + "function-parameters": { + "name": "meta.parameters.js", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.js" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.js" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#decorator" + }, + { + "include": "#destructuring-parameter" + }, + { + "include": "#parameter-name" + }, + { + "include": "#type-annotation" + }, + { + "include": "#variable-initializer" + }, + { + "name": "punctuation.separator.parameter.js", + "match": "," + } + ] + }, + "type-primitive": { + "name": "support.type.primitive.js", + "match": "(?)\n ))\n )\n )\n)", + "end": "(?<=\\))", + "patterns": [ + { + "include": "#function-parameters" + } + ] + } + ] + }, + "type-operators": { + "patterns": [ + { + "include": "#typeof-operator" + }, + { + "name": "keyword.operator.type.js", + "match": "[&|]" + }, + { + "name": "keyword.operator.expression.keyof.js", + "match": "(?", + "beginCaptures": { + "0": { + "name": "storage.type.function.arrow.js" + } + }, + "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", + "patterns": [ + { + "include": "#comment" + }, + { + "name": "meta.object.type.js", + "begin": "(?<==>)\\s*(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.block.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.js" + } + }, + "patterns": [ + { + "include": "#type-object-members" + } + ] + }, + { + "include": "#type-predicate-operator" + }, + { + "include": "#type" + } + ] + }, + "type-tuple": { + "name": "meta.type.tuple.js", + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "patterns": [ + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "type-name": { + "patterns": [ + { + "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", + "captures": { + "1": { + "name": "entity.name.type.module.js" + }, + "2": { + "name": "punctuation.accessor.js" + } + } + }, + { + "name": "entity.name.type.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + } + ] + }, + "type-parameters": { + "name": "meta.type.parameters.js", + "begin": "(<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.begin.js" + } + }, + "end": "(?=$)|(>)", + "endCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.end.js" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "name": "storage.modifier.js", + "match": "(?)" + }, + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "variable-initializer": { + "patterns": [ + { + "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "support.constant.dom.js" + }, + "3": { + "name": "support.variable.property.dom.js" + } + } + }, + { + "name": "support.class.node.js", + "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", + "patterns": [ + { + "include": "#literal" + }, + { + "include": "#support-objects" + }, + { + "include": "#object-identifiers" + }, + { + "include": "#punctuation-accessor" + }, + { + "name": "entity.name.function.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + }, + { + "include": "#comment" + }, + { + "name": "meta.type.parameters.js", + "begin": "\\<", + "beginCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.begin.js" + } + }, + "end": "\\>", + "endCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.end.js" + } + }, + "patterns": [ + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + { + "include": "#paren-expression" + } + ] + }, + "identifiers": { + "patterns": [ + { + "include": "#object-identifiers" + }, + { + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "entity.name.function.js" + } + } + }, + { + "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.constant.property.js" + } + } + }, + { + "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.property.js" + } + } + }, + { + "name": "variable.other.constant.js", + "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" + }, + { + "name": "variable.other.readwrite.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + } + ] + }, + "object-identifiers": { + "patterns": [ + { + "name": "support.class.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" + }, + { + "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.constant.object.property.js" + }, + "3": { + "name": "variable.other.object.property.js" + } + } + }, + { + "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "variable.other.constant.object.js" + }, + "2": { + "name": "variable.other.object.js" + } + } + } + ] + }, + "cast": { + "patterns": [ + { + "include": "#jsx" + } + ] + }, + "new-expr": { + "name": "new.expr.js", + "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", + "beginCaptures": { + "0": { + "name": "meta.object-literal.key.js" + }, + "1": { + "name": "entity.name.function.js" + }, + "2": { + "name": "punctuation.separator.key-value.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", + "beginCaptures": { + "0": { + "name": "meta.object-literal.key.js" + }, + "1": { + "name": "punctuation.separator.key-value.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "begin": "\\.\\.\\.", + "beginCaptures": { + "0": { + "name": "keyword.operator.spread.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", + "captures": { + "1": { + "name": "variable.other.readwrite.js" + } + } + }, + { + "include": "#punctuation-comma" + } + ] + }, + "expression-operators": { + "patterns": [ + { + "name": "keyword.control.flow.js", + "match": "(?>=|>>>=|\\|=" + }, + { + "name": "keyword.operator.bitwise.shift.js", + "match": "<<|>>>|>>" + }, + { + "name": "keyword.operator.comparison.js", + "match": "===|!==|==|!=" + }, + { + "name": "keyword.operator.relational.js", + "match": "<=|>=|<>|<|>" + }, + { + "name": "keyword.operator.logical.js", + "match": "\\!|&&|\\|\\|" + }, + { + "name": "keyword.operator.bitwise.js", + "match": "\\&|~|\\^|\\|" + }, + { + "name": "keyword.operator.assignment.js", + "match": "\\=" + }, + { + "name": "keyword.operator.decrement.js", + "match": "--" + }, + { + "name": "keyword.operator.increment.js", + "match": "\\+\\+" + }, + { + "name": "keyword.operator.arithmetic.js", + "match": "%|\\*|/|-|\\+" + }, + { + "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", + "captures": { + "1": { + "name": "keyword.operator.arithmetic.js" + } + } + } + ] + }, + "typeof-operator": { + "name": "keyword.operator.expression.typeof.js", + "match": "(?)", + "captures": { + "1": { + "name": "storage.modifier.async.js" + }, + "2": { + "name": "variable.parameter.js" + } + } + }, + { + "name": "meta.arrow.js", + "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", + "beginCaptures": { + "1": { + "name": "storage.modifier.async.js" + } + }, + "end": "(?==>|\\{)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type-parameters" + }, + { + "include": "#function-parameters" + }, + { + "include": "#arrow-return-type" + } + ] + }, + { + "name": "meta.arrow.js", + "begin": "=>", + "beginCaptures": { + "0": { + "name": "storage.type.function.arrow.js" + } + }, + "end": "(?<=\\})|((?!\\{)(?=\\S))", + "patterns": [ + { + "include": "#decl-block" + }, + { + "include": "#expression" + } + ] + } + ] + }, + "arrow-return-type": { + "name": "meta.return.type.arrow.js", + "begin": "(?<=\\))\\s*(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.js" + } + }, + "end": "(?==>|\\{)", + "patterns": [ + { + "name": "meta.object.type.js", + "begin": "(?<=:)\\s*(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.block.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.js" + } + }, + "patterns": [ + { + "include": "#type-object-members" + } + ] + }, + { + "include": "#type-predicate-operator" + }, + { + "include": "#type" + } + ] + }, + "punctuation-comma": { + "name": "punctuation.separator.comma.js", + "match": "," + }, + "punctuation-semicolon": { + "name": "punctuation.terminator.statement.js", + "match": ";" + }, + "punctuation-accessor": { + "name": "punctuation.accessor.js", + "match": "\\." + }, + "paren-expression": { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "meta.brace.round.js" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "meta.brace.round.js" + } + }, + "patterns": [ + { + "include": "#expression" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "qstring-double": { + "name": "string.quoted.double.js", + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(\")|((?:[^\\\\\\n])$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "invalid.illegal.newline.js" + } + }, + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "qstring-single": { + "name": "string.quoted.single.js", + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(\\')|((?:[^\\\\\\n])$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "invalid.illegal.newline.js" + } + }, + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "regex": { + "patterns": [ + { + "name": "string.regexp.js", + "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(/)([gimuy]*)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "keyword.other.js" + } + }, + "patterns": [ + { + "include": "#regexp" + } + ] + }, + { + "name": "string.regexp.js", + "begin": "(?\\s*$)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.js" + } + }, + "end": "(?=$)", + "patterns": [ + { + "name": "meta.tag.js", + "begin": "(<)(reference|amd-dependency|amd-module)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.directive.js" + }, + "2": { + "name": "entity.name.tag.directive.js" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.directive.js" + } + }, + "patterns": [ + { + "name": "entity.other.attribute-name.directive.js", + "match": "path|types|no-default-lib|name" + }, + { + "name": "keyword.operator.assignment.js", + "match": "=" + }, + { + "include": "#string" + } + ] + } + ] + }, + "docblock": { + "patterns": [ + { + "name": "storage.type.class.jsdoc", + "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", + "captures": { + "0": { + "name": "other.meta.jsdoc" + }, + "1": { + "name": "entity.name.type.instance.jsdoc" + }, + "2": { + "name": "variable.other.jsdoc" + }, + "3": { + "name": "other.description.jsdoc" + } + } + }, + { + "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", + "captures": { + "0": { + "name": "other.meta.jsdoc" + }, + "1": { + "name": "entity.name.type.instance.jsdoc" + }, + "2": { + "name": "other.description.jsdoc" + } + } + } + ] + }, + "jsx-tag-attributes": { + "patterns": [ + { + "include": "#jsx-tag-attribute-name" + }, + { + "include": "#jsx-tag-attribute-assignment" + }, + { + "include": "#jsx-string-double-quoted" + }, + { + "include": "#jsx-string-single-quoted" + }, + { + "include": "#jsx-evaluated-code" + } + ] + }, + "jsx-tag-attribute-name": { + "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", + "captures": { + "1": { + "name": "entity.other.attribute-name.js" + } + } + }, + "jsx-tag-attribute-assignment": { + "name": "keyword.operator.assignment.js", + "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" + }, + "jsx-string-double-quoted": { + "name": "string.quoted.double.js", + "begin": "\"", + "end": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-string-single-quoted": { + "name": "string.quoted.single.js", + "begin": "'", + "end": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-entities": { + "patterns": [ + { + "name": "constant.character.entity.js", + "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", + "captures": { + "1": { + "name": "punctuation.definition.entity.js" + }, + "3": { + "name": "punctuation.definition.entity.js" + } + } + }, + { + "name": "invalid.illegal.bad-ampersand.js", + "match": "&" + } + ] + }, + "jsx-evaluated-code": { + "name": "meta.embedded.expression.js", + "begin": "\\{", + "end": "\\}", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.js" + } + }, + "patterns": [ + { + "include": "#expression" + } + ] + }, + "jsx-tag-attributes-illegal": { + "name": "invalid.illegal.attribute.js", + "match": "\\S+" + }, + "jsx-tag-without-attributes": { + "name": "meta.tag.without-attributes.js", + "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", + "end": "()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "contentName": "meta.jsx.children.tsx", + "patterns": [ + { + "include": "#jsx-children" + } + ] + }, + "jsx-tag-in-expression": { + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(/>)|(?:())", + "endCaptures": { + "0": { + "name": "meta.tag.js" + }, + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "entity.name.tag.js" + }, + "4": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-tag" + } + ] + }, + "jsx-child-tag": { + "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(/>)|(?:())", + "endCaptures": { + "0": { + "name": "meta.tag.js" + }, + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "entity.name.tag.js" + }, + "4": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-tag" + } + ] + }, + "jsx-tag": { + "name": "meta.tag.js", + "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(?=(/>)|(?:()))", + "patterns": [ + { + "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + } + }, + "end": "(?=[/]?>)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#jsx-tag-attributes" + }, + { + "include": "#jsx-tag-attributes-illegal" + } + ] + }, + { + "begin": "(>)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + } + }, + "end": "(?=" + }, + "jsx-children": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-child-tag" + }, + { + "include": "#jsx-tag-invalid" + }, + { + "include": "#jsx-evaluated-code" + }, + { + "include": "#jsx-entities" + } + ] + }, + "jsx": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-tag-in-expression" + }, + { + "include": "#jsx-tag-invalid" + } + ] + } + }, + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" } diff --git a/grammar/Readme.md b/grammar/Readme.md index 7d4d7ce13..27fac0582 100644 --- a/grammar/Readme.md +++ b/grammar/Readme.md @@ -1,10 +1,13 @@ -Note: The file `JavaScript.tmLanguage.json` is derived from [TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). +Note: The file `JavaScript.tmLanguage.json` is derived from +[TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). # To update the grammar after making changes: 1. npm run update-grammar -2. Re-comment imports in mongoParser.ts that are not used and cause compile errors +2. Re-comment imports in mongoParser.ts that are not used and cause compile + errors # Debugging the grammar -See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to generate the debug info before trying to launch. +See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to +generate the debug info before trying to launch. diff --git a/grammar/configuration.json b/grammar/configuration.json index 42f2e2c1b..82ae3324e 100644 --- a/grammar/configuration.json +++ b/grammar/configuration.json @@ -1,55 +1,39 @@ { - "comments": { - "lineComment": "//", - "blockComment": [ - "/*", - "*/" - ] - }, - "brackets": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ] - ], - "autoClosingPairs": [ - { - "open": "{", - "close": "}" - }, - { - "open": "[", - "close": "]" - }, - { - "open": "(", - "close": ")" - }, - { - "open": "'", - "close": "'", - "notIn": [ - "string", - "comment" - ] - }, - { - "open": "\"", - "close": "\"", - "notIn": [ - "string" - ] - }, - { - "open": "/**", - "close": " */", - "notIn": [ - "string" - ] - } - ] + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"] + ], + "autoClosingPairs": [ + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "'", + "close": "'", + "notIn": ["string", "comment"] + }, + { + "open": "\"", + "close": "\"", + "notIn": ["string"] + }, + { + "open": "/**", + "close": " */", + "notIn": ["string"] + } + ] } diff --git a/gulpfile.ts b/gulpfile.ts index 3e69c1ffd..55888b8c4 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -3,29 +3,36 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { gulp_webpack } from '@microsoft/vscode-azext-dev'; -import * as fse from 'fs-extra'; -import * as gulp from 'gulp'; -import * as path from 'path'; +import { gulp_webpack } from "@microsoft/vscode-azext-dev"; +import * as fse from "fs-extra"; +import * as gulp from "gulp"; +import * as path from "path"; declare let exports: { [key: string]: unknown }; async function prepareForWebpack(): Promise { - const mainJsPath: string = path.join(__dirname, 'main.js'); - let contents: string = (await fse.readFile(mainJsPath)).toString(); - contents = contents - .replace('out/src/extension', 'dist/extension.bundle') - .replace(', true /* ignoreBundle */', ''); - await fse.writeFile(mainJsPath, contents); + const mainJsPath: string = path.join(__dirname, "main.js"); + let contents: string = (await fse.readFile(mainJsPath)).toString(); + contents = contents + .replace("out/src/extension", "dist/extension.bundle") + .replace(", true /* ignoreBundle */", ""); + await fse.writeFile(mainJsPath, contents); } async function cleanReadme(): Promise { - const readmePath: string = path.join(__dirname, 'README.md'); - let data: string = (await fse.readFile(readmePath)).toString(); - data = data.replace(/.*?/gis, ''); - await fse.writeFile(readmePath, data); + const readmePath: string = path.join(__dirname, "README.md"); + let data: string = (await fse.readFile(readmePath)).toString(); + data = data.replace( + /.*?/gis, + "" + ); + await fse.writeFile(readmePath, data); } -exports['webpack-dev'] = gulp.series(prepareForWebpack, () => gulp_webpack('development')); -exports['webpack-prod'] = gulp.series(prepareForWebpack, () => gulp_webpack('production')); +exports["webpack-dev"] = gulp.series(prepareForWebpack, () => + gulp_webpack("development") +); +exports["webpack-prod"] = gulp.series(prepareForWebpack, () => + gulp_webpack("production") +); exports.cleanReadme = cleanReadme; diff --git a/main.js b/main.js index 01717236a..3fa51d0fb 100644 --- a/main.js +++ b/main.js @@ -10,20 +10,24 @@ // This is in a separate file so we can properly measure extension.bundle.js load time. let perfStats = { - loadStartTime: Date.now(), - loadEndTime: undefined + loadStartTime: Date.now(), + loadEndTime: undefined, }; Object.defineProperty(exports, "__esModule", { value: true }); -const extension = require('./out/src/extension'); +const extension = require("./out/src/extension"); async function activate(ctx) { - return await extension.activateInternal(ctx, perfStats, true /* ignoreBundle */); + return await extension.activateInternal( + ctx, + perfStats, + true /* ignoreBundle */ + ); } async function deactivate(ctx) { - return await extension.deactivateInternal(ctx, perfStats); + return await extension.deactivateInternal(ctx, perfStats); } // Export as entrypoints for vscode diff --git a/package.json b/package.json index 69407e037..33e5a421f 100644 --- a/package.json +++ b/package.json @@ -1,1127 +1,1127 @@ { - "name": "vscode-cosmosdb", - "displayName": "Azure Databases", - "version": "0.0.1", - "private": "false", - "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "categories": [ - "Azure" - ], - "keywords": [ - "Cosmos DB", - "DocumentDB", - "Graph", - "Gremlin", - "MongoDB", - "PostgreSQL" - ], - "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", - "bugs": { - "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" - }, - "license": "MIT", - "author": { - "name": "Nikola Hristov", - "email": "nikola@nikolahristov.tech", - "url": "https://nikolahristov.tech" - }, - "publisher": "playform", - "type": "module", - "main": "./main", - "scripts": { - "all": "npm i && npm run lint && npm test", - "build": "tsc", - "clean": "git clean -dfx", - "cleanReadme": "gulp cleanReadme", - "compile": "tsc -watch", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "prepare": "husky install", - "prepublishOnly": "TypeScriptESBuild Source/**/*.ts", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "vscode:prepublish": "npm run webpack-prod", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats" - }, - "contributes": { - "commands": [ - { - "category": "Azure Databases", - "command": "azureDatabases.createServer", - "title": "Create Server...", - "icon": "$(add)" - }, - { - "category": "Cosmos DB", - "command": "azureDatabases.detachDatabaseAccount", - "title": "Detach" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.loadMore", - "title": "Load More" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.refresh", - "title": "Refresh", - "icon": "$(refresh)" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.reportIssue", - "title": "Report Issue..." - }, - { - "category": "Azure Databases", - "command": "azureDatabases.update", - "title": "Update to Cloud", - "icon": "$(cloud-upload)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachDatabaseAccount", - "title": "Attach Database Account...", - "icon": "$(plug)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachEmulator", - "title": "Attach Emulator..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.connectMongoDB", - "title": "Connect to Database..." - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBCollection", - "title": "Create Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDatabase", - "title": "Create Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDocument", - "title": "Create Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBStoredProcedure", - "title": "Create Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraph", - "title": "Create Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraphDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoCollection", - "title": "Create Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDocument", - "title": "Create Document" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.deleteAccount", - "title": "Delete Account..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBCollection", - "title": "Delete Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDatabase", - "title": "Delete Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDocument", - "title": "Delete Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraph", - "title": "Delete Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraphDatabase", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoCollection", - "title": "Delete Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDB", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDocument", - "title": "Delete Document..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeAllMongoCommands", - "title": "Execute All MongoDB Commands" - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeMongoCommand", - "title": "Execute MongoDB Command" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.importDocument", - "title": "Import Document into a Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.launchMongoShell", - "title": "Launch Shell" - }, - { - "category": "MongoDB", - "command": "cosmosDB.newMongoScrapbook", - "title": "New Mongo Scrapbook", - "icon": "$(new-file)" - }, - { - "category": "MongoDB", - "command": "cosmosDB.openCollection", - "title": "Open Collection" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openDocument", - "title": "Open Document" - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.openGraphExplorer", - "title": "Open Graph Explorer" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.configureFirewall", - "title": "Configure Firewall" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.connectDatabase", - "title": "Connect to Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createDatabase", - "title": "Create Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createFunctionQuery", - "title": "Create Function Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createStoredProcedureQuery", - "title": "Create Stored Procedure Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteDatabase", - "title": "Delete Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteFunction", - "title": "Delete Function..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteServer", - "title": "Delete Server..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteTable", - "title": "Delete Table..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.enterCredentials", - "title": "Enter Server Credentials" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.executeQuery", - "title": "Execute Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openFunction", - "title": "Open Function" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.showPasswordlessWiki", - "title": "Learn more about authenticating with Azure Active Directory", - "icon": "$(warning)" - } - ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" - } - } - }, - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } - ], - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" - } - ], - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId==postgres" - } - ], - "editor/title": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "azureDatabases.createServer", - "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", - "group": "1@1" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteServer", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@1" - }, - { - "command": "postgreSQL.showPasswordlessWiki", - "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", - "group": "inline" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@1" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@2" - }, - { - "command": "cosmosDB.connectMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "2@1" - }, - { - "command": "cosmosDB.deleteMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@4" - }, - { - "command": "cosmosDB.deleteMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraphDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteTable", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteFunction", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", - "group": "1@2" - }, - { - "command": "cosmosDB.attachDatabaseAccount", - "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "1@1" - }, - { - "command": "cosmosDB.attachEmulator", - "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", - "group": "1@2" - }, - { - "command": "cosmosDB.openCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "2@1" - }, - { - "command": "postgreSQL.copyConnectionString", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "2@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", - "group": "1@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "2@1" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@3" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@1" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createFunctionQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "1@1" - }, - { - "command": "postgreSQL.createStoredProcedureQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "1@1" - } - ], - "explorer/context": [ - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId == json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId == postgres" - } - ], - "commandPalette": [ - { - "command": "azureDatabases.loadMore", - "when": "never" - }, - { - "command": "azureDatabases.refresh", - "when": "never" - }, - { - "command": "azureDatabases.update", - "when": "never" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "editorLangId == 'mongo'" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "editorLangId == 'mongo'" - }, - { - "command": "postgreSQL.executeQuery", - "when": "editorLangId == 'postgres'" - } - ] - }, - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } - ], - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - } - }, - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], - "dependencies": { - "@azure/arm-cosmosdb": "15.5.0", - "@azure/arm-postgresql": "6.1.0", - "@azure/arm-postgresql-flexible": "7.1.0", - "@azure/cosmos": "4.0.0", - "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.3", - "antlr4ts": "0.5.0-alpha.4", - "bson": "6.2.0", - "fs-extra": "11.1.1", - "mongodb": "6.2.0", - "mongodb-extended-json": "1.10.0", - "open": "9.1.0", - "pg": "8.11.3", - "pg-connection-string": "2.6.2", - "pg-structure": "7.15.0", - "semver": "7.5.4", - "underscore": "1.13.6", - "vscode-json-languageservice": "5.3.7", - "vscode-languageclient": "9.0.1", - "vscode-languageserver": "9.0.1", - "vscode-languageserver-textdocument": "1.0.11", - "vscode-nls": "5.2.0", - "vscode-uri": "3.0.8" - }, - "devDependencies": { - "@azure/arm-resources": "5.2.0", - "@microsoft/eslint-config-azuretools": "0.2.1", - "@microsoft/vscode-azext-dev": "2.0.2", - "@types/copy-webpack-plugin": "8.0.1", - "@types/documentdb": "1.10.11", - "@types/fs-extra": "11.0.3", - "@types/gulp": "4.0.16", - "@types/mocha": "10.0.3", - "@types/mongodb": "4.0.6", - "@types/node": "20.8.9", - "@types/pg": "8.10.7", - "@types/vscode": "1.83.1", - "@typescript-eslint/eslint-plugin": "6.9.0", - "@vscode/test-electron": "2.3.6", - "antlr4ts-cli": "0.5.0-alpha.4", - "copy-webpack-plugin": "11.0.0", - "eslint": "8.52.0", - "eslint-plugin-import": "2.29.0", - "glob": "10.3.10", - "gulp": "4.0.2", - "husky": "8.0.3", - "mocha": "10.2.0", - "mocha-junit-reporter": "2.2.1", - "mocha-multi-reporters": "1.5.1", - "ts-node": "10.9.1", - "typescript": "5.2.2", - "typescript-esbuild": "0.3.1", - "vsce": "1.87.0", - "webpack": "5.89.0", - "webpack-cli": "5.1.4", - "webpack-log": "3.0.2" - }, - "extensionDependencies": [ - "ms-azuretools.vscode-azureresourcegroups", - "ms-vscode.azure-account" - ], - "engines": { - "vscode": "1.66.0" - }, - "publishConfig": { - "access": "public" - }, - "icon": "resources/databases.png", - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "preview": true, - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255" + "name": "vscode-cosmosdb", + "displayName": "Azure Databases", + "version": "0.0.1", + "private": "false", + "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", + "categories": [ + "Azure" + ], + "keywords": [ + "Cosmos DB", + "DocumentDB", + "Graph", + "Gremlin", + "MongoDB", + "PostgreSQL" + ], + "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", + "bugs": { + "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" + }, + "license": "MIT", + "author": { + "name": "Nikola Hristov", + "email": "nikola@nikolahristov.tech", + "url": "https://nikolahristov.tech" + }, + "publisher": "playform", + "type": "module", + "main": "./main", + "scripts": { + "all": "npm i && npm run lint && npm test", + "build": "tsc", + "clean": "git clean -dfx", + "cleanReadme": "gulp cleanReadme", + "compile": "tsc -watch", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "prepare": "husky install", + "prepublishOnly": "TypeScriptESBuild 'Source/**/*.ts'", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "vscode:prepublish": "npm run webpack-prod", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats" + }, + "contributes": { + "commands": [ + { + "category": "Azure Databases", + "command": "azureDatabases.createServer", + "title": "Create Server...", + "icon": "$(add)" + }, + { + "category": "Cosmos DB", + "command": "azureDatabases.detachDatabaseAccount", + "title": "Detach" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.loadMore", + "title": "Load More" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.reportIssue", + "title": "Report Issue..." + }, + { + "category": "Azure Databases", + "command": "azureDatabases.update", + "title": "Update to Cloud", + "icon": "$(cloud-upload)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachDatabaseAccount", + "title": "Attach Database Account...", + "icon": "$(plug)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachEmulator", + "title": "Attach Emulator..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.connectMongoDB", + "title": "Connect to Database..." + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBCollection", + "title": "Create Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDatabase", + "title": "Create Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDocument", + "title": "Create Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBStoredProcedure", + "title": "Create Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraph", + "title": "Create Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraphDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoCollection", + "title": "Create Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDocument", + "title": "Create Document" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.deleteAccount", + "title": "Delete Account..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBCollection", + "title": "Delete Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDatabase", + "title": "Delete Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDocument", + "title": "Delete Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraph", + "title": "Delete Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraphDatabase", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoCollection", + "title": "Delete Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDB", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDocument", + "title": "Delete Document..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeAllMongoCommands", + "title": "Execute All MongoDB Commands" + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeMongoCommand", + "title": "Execute MongoDB Command" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.importDocument", + "title": "Import Document into a Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.launchMongoShell", + "title": "Launch Shell" + }, + { + "category": "MongoDB", + "command": "cosmosDB.newMongoScrapbook", + "title": "New Mongo Scrapbook", + "icon": "$(new-file)" + }, + { + "category": "MongoDB", + "command": "cosmosDB.openCollection", + "title": "Open Collection" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openDocument", + "title": "Open Document" + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.openGraphExplorer", + "title": "Open Graph Explorer" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.configureFirewall", + "title": "Configure Firewall" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.connectDatabase", + "title": "Connect to Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createDatabase", + "title": "Create Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createFunctionQuery", + "title": "Create Function Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createStoredProcedureQuery", + "title": "Create Stored Procedure Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteDatabase", + "title": "Delete Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteFunction", + "title": "Delete Function..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteServer", + "title": "Delete Server..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteTable", + "title": "Delete Table..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.enterCredentials", + "title": "Enter Server Credentials" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.executeQuery", + "title": "Execute Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openFunction", + "title": "Open Function" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.showPasswordlessWiki", + "title": "Learn more about authenticating with Azure Active Directory", + "icon": "$(warning)" + } + ], + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null + }, + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] + }, + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 + }, + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" + }, + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" + }, + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + }, + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" + ], + "extensions": [ + ".mongo" + ], + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" + ], + "extensions": [ + ".psql" + ] + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" + } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId==postgres" + } + ], + "editor/title": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "azureDatabases.createServer", + "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", + "group": "1@1" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteServer", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@1" + }, + { + "command": "postgreSQL.showPasswordlessWiki", + "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", + "group": "inline" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@1" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@2" + }, + { + "command": "cosmosDB.connectMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "2@1" + }, + { + "command": "cosmosDB.deleteMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@4" + }, + { + "command": "cosmosDB.deleteMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraphDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteTable", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteFunction", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", + "group": "1@2" + }, + { + "command": "cosmosDB.attachDatabaseAccount", + "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "1@1" + }, + { + "command": "cosmosDB.attachEmulator", + "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", + "group": "1@2" + }, + { + "command": "cosmosDB.openCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "2@1" + }, + { + "command": "postgreSQL.copyConnectionString", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "2@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", + "group": "1@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "2@1" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@3" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@1" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createFunctionQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "1@1" + }, + { + "command": "postgreSQL.createStoredProcedureQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "1@1" + } + ], + "explorer/context": [ + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId == json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId == postgres" + } + ], + "commandPalette": [ + { + "command": "azureDatabases.loadMore", + "when": "never" + }, + { + "command": "azureDatabases.refresh", + "when": "never" + }, + { + "command": "azureDatabases.update", + "when": "never" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "editorLangId == 'mongo'" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "editorLangId == 'mongo'" + }, + { + "command": "postgreSQL.executeQuery", + "when": "editorLangId == 'postgres'" + } + ] + }, + "submenus": [ + { + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" + } + ], + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" + }, + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } + ], + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." + } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] + } + } + }, + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "dependencies": { + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.2.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" + }, + "devDependencies": { + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.1", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.11", + "@types/fs-extra": "11.0.3", + "@types/gulp": "4.0.16", + "@types/mocha": "10.0.3", + "@types/mongodb": "4.0.6", + "@types/node": "20.8.9", + "@types/pg": "8.10.7", + "@types/vscode": "1.83.1", + "@typescript-eslint/eslint-plugin": "6.9.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.52.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", + "typescript-esbuild": "0.3.1", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2" + }, + "extensionDependencies": [ + "ms-azuretools.vscode-azureresourcegroups", + "ms-vscode.azure-account" + ], + "engines": { + "vscode": "1.66.0" + }, + "publishConfig": { + "access": "public" + }, + "icon": "resources/databases.png", + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "preview": true, + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255" } diff --git a/resources/icons/theme-agnostic/CosmosDBAccount.svg b/resources/icons/theme-agnostic/CosmosDBAccount.svg index e6d580065..30b8e8f50 100644 --- a/resources/icons/theme-agnostic/CosmosDBAccount.svg +++ b/resources/icons/theme-agnostic/CosmosDBAccount.svg @@ -1,22 +1,35 @@ - - - - - - - - - - - Icon-databases-121 - - - - - - - - - - + + + + + + + + + + + Icon-databases-121 + + + + + + + + + + diff --git a/resources/icons/theme-agnostic/PostgresServer.svg b/resources/icons/theme-agnostic/PostgresServer.svg index e247e4e71..11be78e38 100644 --- a/resources/icons/theme-agnostic/PostgresServer.svg +++ b/resources/icons/theme-agnostic/PostgresServer.svg @@ -1 +1,27 @@ -Icon-databases-131 \ No newline at end of file + + + + + + + + + + + + + Icon-databases-131 + + + + + + diff --git a/test/attachedAccountsTreeItem.test.ts b/test/attachedAccountsTreeItem.test.ts index be76cad51..9f1d4675b 100644 --- a/test/attachedAccountsTreeItem.test.ts +++ b/test/attachedAccountsTreeItem.test.ts @@ -3,25 +3,47 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { AttachedAccountsTreeItem, MONGO_CONNECTION_EXPECTED } from '../extension.bundle'; +import * as assert from "assert"; +import { + AttachedAccountsTreeItem, + MONGO_CONNECTION_EXPECTED, +} from "../extension.bundle"; -function assertConnectionValid(connectionString: string, expected: string | undefined): void { - const actual = AttachedAccountsTreeItem.validateMongoConnectionString(connectionString); - assert.equal(actual, expected); +function assertConnectionValid( + connectionString: string, + expected: string | undefined +): void { + const actual = + AttachedAccountsTreeItem.validateMongoConnectionString( + connectionString + ); + assert.equal(actual, expected); } suite(`attachedAccountsTreeItem`, () => { - suite(`validateDocDBConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] + suite(`validateDocDBConnectionString`, () => { + // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): + // mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - test('allows "mongodb://"', () => assertConnectionValid(`mongodb://your-mongo.documents.azure.com:10255`, undefined)); + test('allows "mongodb://"', () => + assertConnectionValid( + `mongodb://your-mongo.documents.azure.com:10255`, + undefined + )); - test('allows "mongodb+srv://"', () => assertConnectionValid(`mongodb+srv://usr:pwd@mongodb.net:27017`, undefined)); + test('allows "mongodb+srv://"', () => + assertConnectionValid( + `mongodb+srv://usr:pwd@mongodb.net:27017`, + undefined + )); - test('rejects bad prefix', () => assertConnectionValid(`http://localhost/`, MONGO_CONNECTION_EXPECTED)); + test("rejects bad prefix", () => + assertConnectionValid( + `http://localhost/`, + MONGO_CONNECTION_EXPECTED + )); - test('rejects null', () => assertConnectionValid(null!, MONGO_CONNECTION_EXPECTED)); - }); + test("rejects null", () => + assertConnectionValid(null!, MONGO_CONNECTION_EXPECTED)); + }); }); diff --git a/test/docDBConnectionStrings.test.ts b/test/docDBConnectionStrings.test.ts index e04c0a96f..a66fc72ba 100644 --- a/test/docDBConnectionStrings.test.ts +++ b/test/docDBConnectionStrings.test.ts @@ -3,59 +3,149 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { emulatorPassword, parseDocDBConnectionString } from '../extension.bundle'; - -function testConnectionString(connectionString: string, expectedEndpoint: string, expectedKey: string, expectedDatabaseName: string | undefined): void { - const parsedCS = parseDocDBConnectionString(connectionString); - assert.equal(parsedCS.documentEndpoint, expectedEndpoint); - assert.equal(parsedCS.masterKey, expectedKey); - assert.equal(parsedCS.databaseName, expectedDatabaseName); +import * as assert from "assert"; +import { + emulatorPassword, + parseDocDBConnectionString, +} from "../extension.bundle"; + +function testConnectionString( + connectionString: string, + expectedEndpoint: string, + expectedKey: string, + expectedDatabaseName: string | undefined +): void { + const parsedCS = parseDocDBConnectionString(connectionString); + assert.equal(parsedCS.documentEndpoint, expectedEndpoint); + assert.equal(parsedCS.masterKey, expectedKey); + assert.equal(parsedCS.databaseName, expectedDatabaseName); } suite(`docDBConnectionStrings`, () => { - test(`Without database name`, () => { - // Testing different ordering, different use of ';', different casing, etc. - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString(' AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/; AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('accountendpoint=https://abcdef.documents.azure.com:443/;accountkey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - - // emulator - testConnectionString(`AccountEndpoint=https://localhost:10255/;AccountKey=${emulatorPassword};`, 'https://localhost:10255/', emulatorPassword, undefined); - - // Testing other properties - const parsedCS = parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;'); - assert.equal(parsedCS.hostName, 'abcdef.documents.azure.com'); - assert.equal(parsedCS.port, '443'); - assert.equal(parsedCS.accountId, 'abcdef.documents.azure.com:443'); - assert.equal(parsedCS.fullId, 'abcdef.documents.azure.com:443'); - }); - - test(`With database name`, () => { - // Testing different ordering, different use of ';', different casing, etc. - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=abcd;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('Database=abcd;AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - - // Testing other properties - const parsedCS = parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd'); - assert.equal(parsedCS.hostName, 'abcdef.documents.azure.com'); - assert.equal(parsedCS.port, '443'); - assert.equal(parsedCS.accountId, 'abcdef.documents.azure.com:443'); - assert.equal(parsedCS.fullId, 'abcdef.documents.azure.com:443/abcd'); - }); - - test(`Invalid connection strings`, () => { - assert.throws(() => parseDocDBConnectionString('')); - assert.throws(() => parseDocDBConnectionString('AccountKey=abcdef==')); - assert.throws(() => parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/')); - assert.throws(() => parseDocDBConnectionString('mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb')); - }); + test(`Without database name`, () => { + // Testing different ordering, different use of ';', different casing, etc. + testConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + " AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/; AccountKey=abcdef==", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "accountendpoint=https://abcdef.documents.azure.com:443/;accountkey=abcdef==", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + testConnectionString( + "AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=;", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + undefined + ); + + // emulator + testConnectionString( + `AccountEndpoint=https://localhost:10255/;AccountKey=${emulatorPassword};`, + "https://localhost:10255/", + emulatorPassword, + undefined + ); + + // Testing other properties + const parsedCS = parseDocDBConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;" + ); + assert.equal(parsedCS.hostName, "abcdef.documents.azure.com"); + assert.equal(parsedCS.port, "443"); + assert.equal(parsedCS.accountId, "abcdef.documents.azure.com:443"); + assert.equal(parsedCS.fullId, "abcdef.documents.azure.com:443"); + }); + + test(`With database name`, () => { + // Testing different ordering, different use of ';', different casing, etc. + testConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + "abcd" + ); + testConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd;", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + "abcd" + ); + testConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=abcd;AccountKey=abcdef==", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + "abcd" + ); + testConnectionString( + "Database=abcd;AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;", + "https://abcdef.documents.azure.com:443/", + "abcdef==", + "abcd" + ); + + // Testing other properties + const parsedCS = parseDocDBConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd" + ); + assert.equal(parsedCS.hostName, "abcdef.documents.azure.com"); + assert.equal(parsedCS.port, "443"); + assert.equal(parsedCS.accountId, "abcdef.documents.azure.com:443"); + assert.equal(parsedCS.fullId, "abcdef.documents.azure.com:443/abcd"); + }); + + test(`Invalid connection strings`, () => { + assert.throws(() => parseDocDBConnectionString("")); + assert.throws(() => parseDocDBConnectionString("AccountKey=abcdef==")); + assert.throws(() => + parseDocDBConnectionString( + "AccountEndpoint=https://abcdef.documents.azure.com:443/" + ) + ); + assert.throws(() => + parseDocDBConnectionString( + "mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb" + ) + ); + }); }); diff --git a/test/documentLabel.test.ts b/test/documentLabel.test.ts index 29cde94c8..3bc5d6c74 100644 --- a/test/documentLabel.test.ts +++ b/test/documentLabel.test.ts @@ -3,27 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { getDocumentTreeItemLabel } from '../extension.bundle'; +import * as assert from "assert"; +import { getDocumentTreeItemLabel } from "../extension.bundle"; suite("Document Label Tests", () => { - test("Non-zero number", () => { - const doc = { name: 4, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), 4); - }); + test("Non-zero number", () => { + const doc = { name: 4, _id: "12345678901234567890123456789012" }; + assert.equal(getDocumentTreeItemLabel(doc), 4); + }); - test("zero (number)", () => { - const doc = { name: 0, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), 0); - }); + test("zero (number)", () => { + const doc = { name: 0, _id: "12345678901234567890123456789012" }; + assert.equal(getDocumentTreeItemLabel(doc), 0); + }); - test("Empty string", () => { - const doc = { name: "", _id: "" }; - assert.equal(getDocumentTreeItemLabel(doc), ""); - }); + test("Empty string", () => { + const doc = { name: "", _id: "" }; + assert.equal(getDocumentTreeItemLabel(doc), ""); + }); - test("Null", () => { - const doc = { name: null, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), doc._id); - }); + test("Null", () => { + const doc = { name: null, _id: "12345678901234567890123456789012" }; + assert.equal(getDocumentTreeItemLabel(doc), doc._id); + }); }); diff --git a/test/global.test.ts b/test/global.test.ts index f3fd38670..cb89517b0 100644 --- a/test/global.test.ts +++ b/test/global.test.ts @@ -3,18 +3,18 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TestOutputChannel, TestUserInput } from '@microsoft/vscode-azext-dev'; -import * as vscode from 'vscode'; -import { ext, registerOnActionStartHandler } from '../extension.bundle'; +import { TestOutputChannel, TestUserInput } from "@microsoft/vscode-azext-dev"; +import * as vscode from "vscode"; +import { ext, registerOnActionStartHandler } from "../extension.bundle"; // Runs before all tests suiteSetup(async function (this: Mocha.Context): Promise { - this.timeout(2 * 60 * 1000); - await vscode.commands.executeCommand('azureDatabases.refresh'); // activate the extension before tests begin - ext.outputChannel = new TestOutputChannel(); + this.timeout(2 * 60 * 1000); + await vscode.commands.executeCommand("azureDatabases.refresh"); // activate the extension before tests begin + ext.outputChannel = new TestOutputChannel(); - registerOnActionStartHandler(context => { - // Use `TestUserInput` by default so we get an error if an unexpected call to `context.ui` occurs, rather than timing out - context.ui = new TestUserInput(vscode); - }); + registerOnActionStartHandler((context) => { + // Use `TestUserInput` by default so we get an error if an unexpected call to `context.ui` occurs, rather than timing out + context.ui = new TestUserInput(vscode); + }); }); diff --git a/test/improveError.test.ts b/test/improveError.test.ts index 25ae0a35e..63dc04bdc 100644 --- a/test/improveError.test.ts +++ b/test/improveError.test.ts @@ -3,22 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { improveError } from '../extension.bundle'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as assert from "assert"; +import { improveError } from "../extension.bundle"; suite("improveError", () => { - test("no change", () => { - const msg: string = "where is c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe?"; - const improved: unknown = improveError(msg); + test("no change", () => { + const msg: string = + "where is c:\\Program Files\\MongoDBServer\\4.0\\bin\\mongo.exe?"; + const improved: unknown = improveError(msg); - assert.equal(parseError(improved).message, msg); - }); + assert.equal(parseError(improved).message, msg); + }); - test("spawn ENOENT", () => { - const msg: string = "spawn c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe ENOENT"; - const improved: unknown = improveError(msg); + test("spawn ENOENT", () => { + const msg: string = + "spawn c:\\Program Files\\MongoDBServer\\4.0\\bin\\mongo.exe ENOENT"; + const improved: unknown = improveError(msg); - assert.equal(parseError(improved).message, "Could not find c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe"); - }); + assert.equal( + parseError(improved).message, + "Could not find c:\\Program Files\\MongoDBServer\\4.0\\bin\\mongo.exe" + ); + }); }); diff --git a/test/index.ts b/test/index.ts index bfb035776..3a53a60d3 100644 --- a/test/index.ts +++ b/test/index.ts @@ -3,53 +3,58 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as glob from 'glob'; -import * as Mocha from 'mocha'; -import * as path from 'path'; +import * as glob from "glob"; +import * as Mocha from "mocha"; +import * as path from "path"; export async function run(): Promise { - const options: Mocha.MochaOptions = { - ui: 'tdd', - color: true, - reporter: 'mocha-multi-reporters', - reporterOptions: { - reporterEnabled: 'spec, mocha-junit-reporter', - mochaJunitReporterReporterOptions: { - mochaFile: path.resolve(__dirname, '..', '..', 'test-results.xml') - } - } - }; + const options: Mocha.MochaOptions = { + ui: "tdd", + color: true, + reporter: "mocha-multi-reporters", + reporterOptions: { + reporterEnabled: "spec, mocha-junit-reporter", + mochaJunitReporterReporterOptions: { + mochaFile: path.resolve( + __dirname, + "..", + "..", + "test-results.xml" + ), + }, + }, + }; - addEnvVarsToMochaOptions(options); - console.log(`Mocha options: ${JSON.stringify(options, undefined, 2)}`); + addEnvVarsToMochaOptions(options); + console.log(`Mocha options: ${JSON.stringify(options, undefined, 2)}`); - const mocha = new Mocha(options); - console.log("get files"); - const files: string[] = await new Promise((resolve, reject) => { - // tests in unit/ folder must run without vscode context. - // Skip them when running integration tests in a vscode instance. - glob('{!(unit)/,}*.test.js', { cwd: __dirname }, (err, result) => { - err ? reject(err) : resolve(result); - }); - }); - files.forEach(f => mocha.addFile(path.resolve(__dirname, f))); + const mocha = new Mocha(options); + console.log("get files"); + const files: string[] = await new Promise((resolve, reject) => { + // tests in unit/ folder must run without vscode context. + // Skip them when running integration tests in a vscode instance. + glob("{!(unit)/,}*.test.js", { cwd: __dirname }, (err, result) => { + err ? reject(err) : resolve(result); + }); + }); + files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); - const failures = await new Promise(resolve => mocha.run(resolve)); - if (failures > 0) { - throw new Error(`${failures} tests failed.`); - } + const failures = await new Promise((resolve) => mocha.run(resolve)); + if (failures > 0) { + throw new Error(`${failures} tests failed.`); + } } function addEnvVarsToMochaOptions(options: Mocha.MochaOptions): void { - for (const envVar of Object.keys(process.env)) { - const match: RegExpMatchArray | null = envVar.match(/^mocha_(.+)/i); - if (match) { - const [, option] = match; - let value: string | number = process.env[envVar] || ''; - if (typeof value === 'string' && !isNaN(parseInt(value))) { - value = parseInt(value); - } - (options)[option] = value; - } - } + for (const envVar of Object.keys(process.env)) { + const match: RegExpMatchArray | null = envVar.match(/^mocha_(.+)/i); + if (match) { + const [, option] = match; + let value: string | number = process.env[envVar] || ""; + if (typeof value === "string" && !isNaN(parseInt(value))) { + value = parseInt(value); + } + (options)[option] = value; + } + } } diff --git a/test/mongoConnectionStrings.test.ts b/test/mongoConnectionStrings.test.ts index 4560342a7..e29477292 100644 --- a/test/mongoConnectionStrings.test.ts +++ b/test/mongoConnectionStrings.test.ts @@ -3,163 +3,499 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { addDatabaseToAccountConnectionString, emulatorPassword, encodeMongoConnectionString, getDatabaseNameFromConnectionString, isCosmosEmulatorConnectionString } from '../extension.bundle'; - -function testDatabaseToAccountConnectionString(connectionString: string, databaseName: string, expectedConnectionString: string | undefined): void { - const databaseConnectionString = addDatabaseToAccountConnectionString(connectionString, databaseName); - assert.equal(databaseConnectionString, expectedConnectionString); +import * as assert from "assert"; +import { + addDatabaseToAccountConnectionString, + emulatorPassword, + encodeMongoConnectionString, + getDatabaseNameFromConnectionString, + isCosmosEmulatorConnectionString, +} from "../extension.bundle"; + +function testDatabaseToAccountConnectionString( + connectionString: string, + databaseName: string, + expectedConnectionString: string | undefined +): void { + const databaseConnectionString = addDatabaseToAccountConnectionString( + connectionString, + databaseName + ); + assert.equal(databaseConnectionString, expectedConnectionString); } -function testDatabaseNameFromConectionString(connectionString: string, expectedDatabaseName: string | undefined): void { - const databaseName = getDatabaseNameFromConnectionString(connectionString); - assert.equal(databaseName, expectedDatabaseName); +function testDatabaseNameFromConectionString( + connectionString: string, + expectedDatabaseName: string | undefined +): void { + const databaseName = getDatabaseNameFromConnectionString(connectionString); + assert.equal(databaseName, expectedDatabaseName); } -function testIsCosmosEmulatorConnectionString(connectionString: string, expected: boolean): void { - const actual: boolean = isCosmosEmulatorConnectionString(connectionString); - assert.equal(actual, expected); +function testIsCosmosEmulatorConnectionString( + connectionString: string, + expected: boolean +): void { + const actual: boolean = isCosmosEmulatorConnectionString(connectionString); + assert.equal(actual, expected); } -function testEncodeMongoConnectionString(connectionString: string, expectedConnectionString: string): void { - connectionString = encodeMongoConnectionString(connectionString); - assert.equal(connectionString, expectedConnectionString); +function testEncodeMongoConnectionString( + connectionString: string, + expectedConnectionString: string +): void { + connectionString = encodeMongoConnectionString(connectionString); + assert.equal(connectionString, expectedConnectionString); } suite(`mongoCollectionStrings`, () => { - test(`getDatabaseNameFromConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - testDatabaseNameFromConectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, undefined); - testDatabaseNameFromConectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, 'our-mongo'); - - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, undefined); - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, undefined); - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/dbname`, `dbname`); - - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, undefined); - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test`, 'my-database'); - - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, undefined); - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, undefined); - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/db`, 'db'); - - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/`, undefined); - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/db`, 'db'); - - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, undefined); - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB`, 'MYDB'); - - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, undefined); - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, 'my_db'); - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, undefined); - testDatabaseNameFromConectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, 'hello'); - testDatabaseNameFromConectionString(`mongodb://localhost`, undefined); - testDatabaseNameFromConectionString(`mongodb://localhost/db`, 'db'); - testDatabaseNameFromConectionString(`mongodb://sysop:moon@localhost/records`, 'records'); - testDatabaseNameFromConectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/db`, 'db'); - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc`, 'abc'); - - // special characters - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl`, 'def-ghi_jkl'); - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/Icantlikespaces`, 'Icantlikespaces'); - - // emulator: mongodb://localhost:C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==@localhost:10255?ssl=true - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin?ssl=true`, 'admin'); - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin-master?ssl=true`, 'admin-master'); - // test characters mentioned in : https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Database-Names-for-Windows - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin!@%^()-_,[]?ssl=true`, 'admin!@%^()-_,[]'); - - }); - - test('addDatabaseToAccountConnectionString', () => { - testDatabaseToAccountConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, 'somedatabase', 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/somedatabase?ssl=true&replicaSet=globaldb'); - testDatabaseToAccountConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, 'our-mongo', 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb'); - - testDatabaseToAccountConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, 'mydata', 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/mydata'); - testDatabaseToAccountConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, 'database', 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/database'); - testDatabaseToAccountConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, 'database', 'mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database'); - - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, 'my-database', 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test'); - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, 'my-database', 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?'); - - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, 'undefined', 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined'); - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, 'undefined', 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined'); - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, '(NoSQL)data', 'mongodb://r1.example.net:27017,r2.example.net:27017/(NoSQL)data'); - - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, 'undefined', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/undefined?replicaSet=mySet&authSource=authDB'); - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, 'MYDB', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB'); - - testDatabaseToAccountConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, 'basetoadd', 'mongodb+srv://server.example.com/basetoadd?connectTimeoutMS=300000&authSource=aDifferentAuthDB?'); - - testDatabaseToAccountConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, '', 'mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB'); - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, 'not_mydatabase', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/not_mydatabase?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB'); - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, '', 'mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000'); - testDatabaseToAccountConnectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, 'hellno', 'mongodb://host.example.com/hellno?readPreference=secondary&maxStalenessSeconds=120'); - testDatabaseToAccountConnectionString(`mongodb://localhost`, '', 'mongodb://localhost/'); - testDatabaseToAccountConnectionString(`mongodb://localhost/db`, 'new{}db', `mongodb://localhost/${encodeURIComponent("new{}db")}`); - testDatabaseToAccountConnectionString(`mongodb://sysop:moon@localhost/records`, 'records', 'mongodb://sysop:moon@localhost/records'); - testDatabaseToAccountConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, 'notfun', 'mongodb://%2Ftmp%2Fmongodb-27017.sock/notfun'); - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, 'notsure', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/notsure?ssl=true'); - - // special characters - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, 'def-ghi_jkl', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl?'); - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, 'icantlikespaces', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/icantlikespaces'); - - // Emulator - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin?ssl=true`); - // Collection within emulator - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin-master', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin-master?ssl=true`); - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin!@%^()-_,[]', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/${encodeURIComponent("admin!@%^()-_,[]")}?ssl=true`); - }); - - test('isCosmosEmulatorConnectionString', () => { - testIsCosmosEmulatorConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, false); - testIsCosmosEmulatorConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, false); - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, false); - testIsCosmosEmulatorConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, false); - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, false); - - testIsCosmosEmulatorConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, false); - testIsCosmosEmulatorConnectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost/db`, false); - testIsCosmosEmulatorConnectionString(`mongodb://sysop:moon@localhost/records`, false); - testIsCosmosEmulatorConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc...`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, false); - - // Emulator - testIsCosmosEmulatorConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, true); - testIsCosmosEmulatorConnectionString(`mongodb://127.0.0.1:${encodeURIComponent(emulatorPassword)}@127.0.0.1:10255/?ssl=true`, true); - testIsCosmosEmulatorConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/database?ssl=true`, true); - }); - - test('encodeMongoConnectionString', () => { - testEncodeMongoConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg%3D%3D@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`); - testEncodeMongoConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`); - testEncodeMongoConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`); - testEncodeMongoConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`); - testEncodeMongoConnectionString(`mongodb://localhost`, `mongodb://localhost`); - testEncodeMongoConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, `mongodb://localhost:${encodeURIComponent(encodeURIComponent(emulatorPassword))}@localhost:10255/?ssl=true`); - testEncodeMongoConnectionString(`mongodb://username@example.com:password@localhost/`, `mongodb://username%40example.com:password@localhost/`); - testEncodeMongoConnectionString(`mongodb://crazy@:/%username:even@crazier%/password@localhost/`, `mongodb://crazy%40%3A%2F%25username:even%40crazier%25%2Fpassword@localhost/`); - }); + test(`getDatabaseNameFromConnectionString`, () => { + // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): + // mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] + + testDatabaseNameFromConectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, + "our-mongo" + ); + + testDatabaseNameFromConectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118/dbname`, + `dbname` + ); + + testDatabaseNameFromConectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test`, + "my-database" + ); + + testDatabaseNameFromConectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/db`, + "db" + ); + + testDatabaseNameFromConectionString( + `mongodb+srv://server.example.com/`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb+srv://server.example.com/db`, + "db" + ); + + testDatabaseNameFromConectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB`, + "MYDB" + ); + + testDatabaseNameFromConectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, + "my_db" + ); + testDatabaseNameFromConectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, + undefined + ); + testDatabaseNameFromConectionString( + `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, + "hello" + ); + testDatabaseNameFromConectionString(`mongodb://localhost`, undefined); + testDatabaseNameFromConectionString(`mongodb://localhost/db`, "db"); + testDatabaseNameFromConectionString( + `mongodb://sysop:moon@localhost/records`, + "records" + ); + testDatabaseNameFromConectionString( + `mongodb://%2Ftmp%2Fmongodb-27017.sock/db`, + "db" + ); + testDatabaseNameFromConectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc`, + "abc" + ); + + // special characters + testDatabaseNameFromConectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl`, + "def-ghi_jkl" + ); + testDatabaseNameFromConectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/Icantlikespaces`, + "Icantlikespaces" + ); + + // emulator: mongodb://localhost:C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==@localhost:10255?ssl=true + testDatabaseNameFromConectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/admin?ssl=true`, + "admin" + ); + testDatabaseNameFromConectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/admin-master?ssl=true`, + "admin-master" + ); + // test characters mentioned in : https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Database-Names-for-Windows + testDatabaseNameFromConectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/admin!@%^()-_,[]?ssl=true`, + "admin!@%^()-_,[]" + ); + }); + + test("addDatabaseToAccountConnectionString", () => { + testDatabaseToAccountConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + "somedatabase", + "mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/somedatabase?ssl=true&replicaSet=globaldb" + ); + testDatabaseToAccountConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, + "our-mongo", + "mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb" + ); + + testDatabaseToAccountConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + "mydata", + "mongodb://dbuser:dbpassword@dbname.mlab.com:14118/mydata" + ); + testDatabaseToAccountConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, + "database", + "mongodb://dbuser:dbpassword@dbname.mlab.com:14118/database" + ); + testDatabaseToAccountConnectionString( + `mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, + "database", + "mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database" + ); + + testDatabaseToAccountConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + "my-database", + "mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test" + ); + testDatabaseToAccountConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, + "my-database", + "mongodb://db1.example.net:27017,db2.example.net:2500/my-database?" + ); + + testDatabaseToAccountConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/`, + "undefined", + "mongodb://r1.example.net:27017,r2.example.net:27017/undefined" + ); + testDatabaseToAccountConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017`, + "undefined", + "mongodb://r1.example.net:27017,r2.example.net:27017/undefined" + ); + testDatabaseToAccountConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, + "(NoSQL)data", + "mongodb://r1.example.net:27017,r2.example.net:27017/(NoSQL)data" + ); + + testDatabaseToAccountConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + "undefined", + "mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/undefined?replicaSet=mySet&authSource=authDB" + ); + testDatabaseToAccountConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + "MYDB", + "mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB" + ); + + testDatabaseToAccountConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, + "basetoadd", + "mongodb+srv://server.example.com/basetoadd?connectTimeoutMS=300000&authSource=aDifferentAuthDB?" + ); + + testDatabaseToAccountConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, + "", + "mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB" + ); + testDatabaseToAccountConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, + "not_mydatabase", + "mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/not_mydatabase?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB" + ); + testDatabaseToAccountConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, + "", + "mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000" + ); + testDatabaseToAccountConnectionString( + `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, + "hellno", + "mongodb://host.example.com/hellno?readPreference=secondary&maxStalenessSeconds=120" + ); + testDatabaseToAccountConnectionString( + `mongodb://localhost`, + "", + "mongodb://localhost/" + ); + testDatabaseToAccountConnectionString( + `mongodb://localhost/db`, + "new{}db", + `mongodb://localhost/${encodeURIComponent("new{}db")}` + ); + testDatabaseToAccountConnectionString( + `mongodb://sysop:moon@localhost/records`, + "records", + "mongodb://sysop:moon@localhost/records" + ); + testDatabaseToAccountConnectionString( + `mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, + "notfun", + "mongodb://%2Ftmp%2Fmongodb-27017.sock/notfun" + ); + testDatabaseToAccountConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, + "notsure", + "mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/notsure?ssl=true" + ); + + // special characters + testDatabaseToAccountConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, + "def-ghi_jkl", + "mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl?" + ); + testDatabaseToAccountConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, + "icantlikespaces", + "mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/icantlikespaces" + ); + + // Emulator + testDatabaseToAccountConnectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/?ssl=true`, + "admin", + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/admin?ssl=true` + ); + // Collection within emulator + testDatabaseToAccountConnectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/?ssl=true`, + "admin-master", + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/admin-master?ssl=true` + ); + testDatabaseToAccountConnectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/?ssl=true`, + "admin!@%^()-_,[]", + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/${encodeURIComponent( + "admin!@%^()-_,[]" + )}?ssl=true` + ); + }); + + test("isCosmosEmulatorConnectionString", () => { + testIsCosmosEmulatorConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, + false + ); + + testIsCosmosEmulatorConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, + false + ); + + testIsCosmosEmulatorConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, + false + ); + + testIsCosmosEmulatorConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, + false + ); + + testIsCosmosEmulatorConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + false + ); + + testIsCosmosEmulatorConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, + false + ); + testIsCosmosEmulatorConnectionString(`mongodb://localhost`, false); + testIsCosmosEmulatorConnectionString(`mongodb://localhost/db`, false); + testIsCosmosEmulatorConnectionString( + `mongodb://sysop:moon@localhost/records`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, + false + ); + + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc...`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, + false + ); + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, + false + ); + + // Emulator + testIsCosmosEmulatorConnectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/?ssl=true`, + true + ); + testIsCosmosEmulatorConnectionString( + `mongodb://127.0.0.1:${encodeURIComponent( + emulatorPassword + )}@127.0.0.1:10255/?ssl=true`, + true + ); + testIsCosmosEmulatorConnectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/database?ssl=true`, + true + ); + }); + + test("encodeMongoConnectionString", () => { + testEncodeMongoConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg%3D%3D@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb` + ); + testEncodeMongoConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118` + ); + testEncodeMongoConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test` + ); + testEncodeMongoConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?` + ); + testEncodeMongoConnectionString( + `mongodb://localhost`, + `mongodb://localhost` + ); + testEncodeMongoConnectionString( + `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:10255/?ssl=true`, + `mongodb://localhost:${encodeURIComponent( + encodeURIComponent(emulatorPassword) + )}@localhost:10255/?ssl=true` + ); + testEncodeMongoConnectionString( + `mongodb://username@example.com:password@localhost/`, + `mongodb://username%40example.com:password@localhost/` + ); + testEncodeMongoConnectionString( + `mongodb://crazy@:/%username:even@crazier%/password@localhost/`, + `mongodb://crazy%40%3A%2F%25username:even%40crazier%25%2Fpassword@localhost/` + ); + }); }); diff --git a/test/mongoGetCommand.test.ts b/test/mongoGetCommand.test.ts index 5a72eae5e..4918849f3 100644 --- a/test/mongoGetCommand.test.ts +++ b/test/mongoGetCommand.test.ts @@ -3,542 +3,647 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { Position } from 'vscode'; -import { findCommandAtPosition, getAllCommandsFromText, MongoCommand, nonNullProp, ObjectID, ObjectId } from '../extension.bundle'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as assert from "assert"; +import { Position } from "vscode"; +import { + findCommandAtPosition, + getAllCommandsFromText, + MongoCommand, + nonNullProp, + ObjectID, + ObjectId, +} from "../extension.bundle"; function expectSingleCommand(text: string): MongoCommand { - const commands = getAllCommandsFromText(text); - if (commands.length > 1) { - assert.ok(false, "Too many commands found"); - } + const commands = getAllCommandsFromText(text); + if (commands.length > 1) { + assert.ok(false, "Too many commands found"); + } - return commands[0]; + return commands[0]; } function testParse( - text: string, - expectedCommand: { collection: string | undefined, name: string | undefined, args: any[] | undefined, firstErrorText?: string } | undefined + text: string, + expectedCommand: + | { + collection: string | undefined; + name: string | undefined; + args: any[] | undefined; + firstErrorText?: string; + } + | undefined ): void { - function testCore(coreText: string): void { - const command = expectSingleCommand(coreText); - if (expectedCommand) { - assert.ok(command, "Expected a command, but found none"); - - assert.equal(command.collection || "", expectedCommand.collection || "", "Parsed collection name is not correct"); - assert.equal(command.name || "", expectedCommand.name || "", "Parsed command name is not correct"); - - const actualArgs = (command.arguments || []).map(arg => JSON.parse(arg)); - assert.deepEqual(actualArgs, expectedCommand.args || [], "Parsed arguments are not correct"); - - } else { - assert.ok(!command, "Found a command, but expecting to find none"); - return; - } - - if (expectedCommand && expectedCommand.firstErrorText) { - assert.equal((command.errors || []).length > 0, true, "Expected at least one error"); - assert.equal(nonNullProp(command, 'errors')[0].message, expectedCommand.firstErrorText, "First error text was incorrect"); - } else { - assert.equal((command.errors || []).length, 0, "Expected no errors"); - } - } - - testCore(text); - - // Test again with LF changed to CR/LF - const crlfText = text.replace(/\n/g, '\r\n'); - testCore(crlfText); - - // Test again with LF changed to multiple CR/LF - const crlf2Text = text.replace(/\n/g, '\r\n\r\n'); - testCore(crlf2Text); - - // Test again with LF changed to CR - const lfText = text.replace(/\n/g, '\r'); - testCore(lfText); - - // Test again with LF changed to tab - const tabText = text.replace(/\n/g, '\t'); - testCore(tabText); - - // Test again with LF changed to space - const spaceText = text.replace(/\n/g, ' '); - testCore(spaceText); + function testCore(coreText: string): void { + const command = expectSingleCommand(coreText); + if (expectedCommand) { + assert.ok(command, "Expected a command, but found none"); + + assert.equal( + command.collection || "", + expectedCommand.collection || "", + "Parsed collection name is not correct" + ); + assert.equal( + command.name || "", + expectedCommand.name || "", + "Parsed command name is not correct" + ); + + const actualArgs = (command.arguments || []).map((arg) => + JSON.parse(arg) + ); + assert.deepEqual( + actualArgs, + expectedCommand.args || [], + "Parsed arguments are not correct" + ); + } else { + assert.ok(!command, "Found a command, but expecting to find none"); + return; + } + + if (expectedCommand && expectedCommand.firstErrorText) { + assert.equal( + (command.errors || []).length > 0, + true, + "Expected at least one error" + ); + assert.equal( + nonNullProp(command, "errors")[0].message, + expectedCommand.firstErrorText, + "First error text was incorrect" + ); + } else { + assert.equal( + (command.errors || []).length, + 0, + "Expected no errors" + ); + } + } + + testCore(text); + + // Test again with LF changed to CR/LF + const crlfText = text.replace(/\n/g, "\r\n"); + testCore(crlfText); + + // Test again with LF changed to multiple CR/LF + const crlf2Text = text.replace(/\n/g, "\r\n\r\n"); + testCore(crlf2Text); + + // Test again with LF changed to CR + const lfText = text.replace(/\n/g, "\r"); + testCore(lfText); + + // Test again with LF changed to tab + const tabText = text.replace(/\n/g, "\t"); + testCore(tabText); + + // Test again with LF changed to space + const spaceText = text.replace(/\n/g, " "); + testCore(spaceText); } -function wrapInQuotes(word: string, numQuotes: number): string { //0 to do nothing, 1 for single quotes, 2 for double quotes - let result: string; - if (numQuotes === 1) { - result = `'${word}'`; - } else if (numQuotes === 2) { - result = `"${word}"`; - } else { - result = word; - } - return result; +function wrapInQuotes(word: string, numQuotes: number): string { + //0 to do nothing, 1 for single quotes, 2 for double quotes + let result: string; + if (numQuotes === 1) { + result = `'${word}'`; + } else if (numQuotes === 2) { + result = `"${word}"`; + } else { + result = word; + } + return result; } suite("scrapbook parsing Tests", () => { - test("find", () => { - const text = "db.find()"; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test("find with semicolon", () => { - const text = "db.find();"; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test("first of two commands, Mac/Linux", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test("second of two commands, Mac/Linux", () => { - const line1 = "db.find()"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test("second of two commands, Mac/Linux, semicolon", () => { - const line1 = "db.find();"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test("first of two commands, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test("second of two commands, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a':'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - }); - - test("second of two commands, lots of blank lines, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a':'b'})"; - const text = `\r\n\r\n\r\n\r\n\r\n\r\n${line1}\r\n\r\n\r\n\r\n\r\n\r\n${line2}\r\n\r\n\r\n\r\n\r\n\r\n`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(5, 0)); - assert.equal(command.text, line2); - }); - - test("first of two commands, Windows, on blank line before second command", () => { - const line1 = "db.find()"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:1})`; - const text = `${line1}\r\n\r\n\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line1); - } - }); - - test("drop", () => { - testParse( - `db.test.drop()`, - { collection: "test", name: "drop", args: [] }); - }); - - test("find, with empty object argument", () => { - testParse( - `db.test.find({})`, - { collection: "test", name: "find", args: [{}] }); - }); - - test("end-of-line comment", () => { - testParse( - `db.test.drop() // Ignore error "ns not found", it means "test" does not exist yet`, - { collection: "test", name: "drop", args: [] }); - }); - - test("multi-line insert from #214", () => { - for (let q = 0; q <= 2; q++) { - testParse( - `db.heroes.insert({\n${wrapInQuotes("id", q)}: 2,\r\n${wrapInQuotes("name", q)}: "Batman",\r\n\r\n${wrapInQuotes("saying", q)}: "I'm Batman"\r})`, - { - collection: "heroes", name: "insert", args: [ - { - id: 2, - name: "Batman", - saying: "I'm Batman" - } - ] - }); - } - }); - - test("find/project from #214", () => { - testParse( - `db.heroes.find({ "id": 2 }, { "saying": 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - }, - { - saying: 1 - } - ] - }); - }); - - test("extraneous input", () => { - testParse( - `db.heros.find(); + test("find", () => { + const text = "db.find()"; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.equal(command.text, text); + }); + + test("find with semicolon", () => { + const text = "db.find();"; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.equal(command.text, text); + }); + + test("first of two commands, Mac/Linux", () => { + const line1 = "db.find()"; + const line2 = "db.insertOne({'a': 'b'})"; + const text = `${line1}\n${line2}`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.equal(command.text, line1); + }); + + test("second of two commands, Mac/Linux", () => { + const line1 = "db.find()"; + for (let q = 0; q <= 2; q++) { + const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; + const text = `${line1}\n${line2}`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(2, 0) + ); + assert.equal(command.text, line2); + } + }); + + test("second of two commands, Mac/Linux, semicolon", () => { + const line1 = "db.find();"; + for (let q = 0; q <= 2; q++) { + const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; + const text = `${line1}\n${line2}`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(2, 0) + ); + assert.equal(command.text, line2); + } + }); + + test("first of two commands, Windows", () => { + const line1 = "db.find()"; + const line2 = "db.insertOne({'a': 'b'})"; + const text = `${line1}\r\n${line2}`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.equal(command.text, line1); + }); + + test("second of two commands, Windows", () => { + const line1 = "db.find()"; + const line2 = "db.insertOne({'a':'b'})"; + const text = `${line1}\r\n${line2}`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(2, 0) + ); + assert.equal(command.text, line2); + }); + + test("second of two commands, lots of blank lines, Windows", () => { + const line1 = "db.find()"; + const line2 = "db.insertOne({'a':'b'})"; + const text = `\r\n\r\n\r\n\r\n\r\n\r\n${line1}\r\n\r\n\r\n\r\n\r\n\r\n${line2}\r\n\r\n\r\n\r\n\r\n\r\n`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(5, 0) + ); + assert.equal(command.text, line2); + }); + + test("first of two commands, Windows, on blank line before second command", () => { + const line1 = "db.find()"; + for (let q = 0; q <= 2; q++) { + const line2 = `db.insertOne({${wrapInQuotes("a", q)}:1})`; + const text = `${line1}\r\n\r\n\r\n${line2}`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(2, 0) + ); + assert.equal(command.text, line1); + } + }); + + test("drop", () => { + testParse(`db.test.drop()`, { + collection: "test", + name: "drop", + args: [], + }); + }); + + test("find, with empty object argument", () => { + testParse(`db.test.find({})`, { + collection: "test", + name: "find", + args: [{}], + }); + }); + + test("end-of-line comment", () => { + testParse( + `db.test.drop() // Ignore error "ns not found", it means "test" does not exist yet`, + { collection: "test", name: "drop", args: [] } + ); + }); + + test("multi-line insert from #214", () => { + for (let q = 0; q <= 2; q++) { + testParse( + `db.heroes.insert({\n${wrapInQuotes( + "id", + q + )}: 2,\r\n${wrapInQuotes( + "name", + q + )}: "Batman",\r\n\r\n${wrapInQuotes( + "saying", + q + )}: "I'm Batman"\r})`, + { + collection: "heroes", + name: "insert", + args: [ + { + id: 2, + name: "Batman", + saying: "I'm Batman", + }, + ], + } + ); + } + }); + + test("find/project from #214", () => { + testParse(`db.heroes.find({ "id": 2 }, { "saying": 1 })`, { + collection: "heroes", + name: "find", + args: [ + { + id: 2, + }, + { + saying: 1, + }, + ], + }); + }); + + test("extraneous input", () => { + testParse( + `db.heros.find(); hello there`, - { - collection: "heros", - name: "find", - args: [], - firstErrorText: "mismatched input 'hello' expecting " - } - ); - }); - - test("empty", () => { - testParse( - "// hello there", - undefined - ); - }); - - test("no command found, errors (will be tacked on to a blank command)", () => { - testParse( - "hello there", - { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input 'hello' expecting " - } - ); - }); - - test("expect error: missing comma in arguments", () => { - testParse( - `db.heroes.find({ "id": 2 } { "saying": 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - } - ], - firstErrorText: "mismatched input '{' expecting {',', ')'}" - } - ); - - testParse( - `db.c.find({"a":[1,2,3]"b":1});`, - { - collection: 'c', - name: 'find', - args: [{ a: [1, 2, 3] }], - firstErrorText: "mismatched input '\"b\"' expecting {',', '}'}" - } - ); - - }); - - //https://github.com/Microsoft/vscode-cosmosdb/issues/467 - test("single quoted property names", () => { - testParse( - `db.heroes.find({ 'id': 2 }, { 'saying': 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - }, - { - saying: 1 - } - ] - }); - }); - test("expect error: missing function name", () => { - // From https://github.com/Microsoft/vscode-cosmosdb/issues/659 - testParse( - `db.c1.`, - { - collection: "c1", - name: "", - args: [], - firstErrorText: "mismatched input '' expecting IDENTIFIER" - } - ); - - testParse( - `db.c1.;`, - { - collection: "c1", - name: "", - args: [], - firstErrorText: "mismatched input ';' expecting IDENTIFIER" - } - ); - - testParse( - `db.c1.(1, "a");`, - { - collection: "c1", - name: "", - args: [ - 1, - 'a' - ], - firstErrorText: "missing IDENTIFIER at '('" - } - ); - - testParse( - `..(1, "a");`, - { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input '.' expecting " - } - ); - - // Just make sure doesn't throw - expectSingleCommand(`db..(1, "a");`); - expectSingleCommand(`..c1(1, "a");`); - }); - - test("multi-line insert from #214", () => { - testParse( - `db.heroes.insert({\n"id": 2,\r\n"name": "Batman",\r\n\r\n"saying": "I'm Batman"\r})`, - { - collection: "heroes", name: "insert", args: [ - { - id: 2, - name: "Batman", - saying: "I'm Batman" - } - ] - }); - }); - - test("Array followed by } on separate line, from #73", () => { - testParse( - `db.createUser({ + { + collection: "heros", + name: "find", + args: [], + firstErrorText: "mismatched input 'hello' expecting ", + } + ); + }); + + test("empty", () => { + testParse("// hello there", undefined); + }); + + test("no command found, errors (will be tacked on to a blank command)", () => { + testParse("hello there", { + collection: undefined, + name: undefined, + args: undefined, + firstErrorText: "mismatched input 'hello' expecting ", + }); + }); + + test("expect error: missing comma in arguments", () => { + testParse(`db.heroes.find({ "id": 2 } { "saying": 1 })`, { + collection: "heroes", + name: "find", + args: [ + { + id: 2, + }, + ], + firstErrorText: "mismatched input '{' expecting {',', ')'}", + }); + + testParse(`db.c.find({"a":[1,2,3]"b":1});`, { + collection: "c", + name: "find", + args: [{ a: [1, 2, 3] }], + firstErrorText: "mismatched input '\"b\"' expecting {',', '}'}", + }); + }); + + //https://github.com/Microsoft/vscode-cosmosdb/issues/467 + test("single quoted property names", () => { + testParse(`db.heroes.find({ 'id': 2 }, { 'saying': 1 })`, { + collection: "heroes", + name: "find", + args: [ + { + id: 2, + }, + { + saying: 1, + }, + ], + }); + }); + test("expect error: missing function name", () => { + // From https://github.com/Microsoft/vscode-cosmosdb/issues/659 + testParse(`db.c1.`, { + collection: "c1", + name: "", + args: [], + firstErrorText: "mismatched input '' expecting IDENTIFIER", + }); + + testParse(`db.c1.;`, { + collection: "c1", + name: "", + args: [], + firstErrorText: "mismatched input ';' expecting IDENTIFIER", + }); + + testParse(`db.c1.(1, "a");`, { + collection: "c1", + name: "", + args: [1, "a"], + firstErrorText: "missing IDENTIFIER at '('", + }); + + testParse(`..(1, "a");`, { + collection: undefined, + name: undefined, + args: undefined, + firstErrorText: "mismatched input '.' expecting ", + }); + + // Just make sure doesn't throw + expectSingleCommand(`db..(1, "a");`); + expectSingleCommand(`..c1(1, "a");`); + }); + + test("multi-line insert from #214", () => { + testParse( + `db.heroes.insert({\n"id": 2,\r\n"name": "Batman",\r\n\r\n"saying": "I'm Batman"\r})`, + { + collection: "heroes", + name: "insert", + args: [ + { + id: 2, + name: "Batman", + saying: "I'm Batman", + }, + ], + } + ); + }); + + test("Array followed by } on separate line, from #73", () => { + testParse( + `db.createUser({ "user": "buddhi", "pwd": "123", "roles": ["readWrite", "dbAdmin"] } )`, - { - collection: undefined, - name: "createUser", - args: [ - { - user: "buddhi", - pwd: "123", - roles: ["readWrite", "dbAdmin"] - } - ] - }); - }); - - test("Multiple line arrays, from #489", () => { - testParse( - ` + { + collection: undefined, + name: "createUser", + args: [ + { + user: "buddhi", + pwd: "123", + roles: ["readWrite", "dbAdmin"], + }, + ], + } + ); + }); + + test("Multiple line arrays, from #489", () => { + testParse( + ` db.c2.insertMany([ {"name": "Stephen", "age": 38, "male": true}, {"name": "Stephen", "age": 38, "male": true} ]) `, - { - collection: "c2", - name: "insertMany", - args: [ - [ - { - name: "Stephen", - age: 38, - male: true - }, - { - name: "Stephen", - age: 38, - male: true - } - ] - ] - }); - }); - - test("test function call that has 2 arguments", () => { - const arg0 = `{"Age": 31}`; - const arg1 = `{"Name": true}`; - const text = `db.find(${arg0}\r\n,\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test("test function call with nested parameters - documents in an array", () => { - const arg0 = `[{"name": "a"}, {"name": "b"}, {"name": "c"}]`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0},\r\n\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test("test function call that has a nested parameter", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const text = `db.test1.insertMany(${arg0})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - }); - test("test function call with erroneous syntax: missing comma", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0} ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 61); - }); - test("test function call with erroneous syntax: missing comma, parameters separated with newline", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": \ntrue}`; - const text = `db.test1.insertMany(${arg0} \n ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 1); - assert.deepEqual(err.range.start.character, 2); - }); - test("test function call with erroneous syntax: missing double quote", () => { - const text = `db.test1.insertMany({name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "missing \':\' at '\": {\"'"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 25); - }); - test("test function call with erroneous syntax: missing opening brace", () => { - const text = `db.test1.insertMany("name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input ':' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 26); - }); - - test("Chained command: to use pretty()", () => { - testParse('db.timesheets.find().pretty();', { - collection: "timesheets", - name: "pretty", - args: [] - }); - }); - - test("ISODate with standard date string", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00Z") });', { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: "2018-05-01T00:00:00.000Z" - }, - name: "Stephen" - } - ] - }); - }); - - test("ISODate without Z in date string", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00") });', { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: "2018-05-01T00:00:00.000Z" - }, - name: "Stephen" - } - ] - }); - }); - - test("Invalid ISODate", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00z") });', { - collection: "c1", - name: "insertOne", - args: [], - firstErrorText: "Invalid time value" - }); - }); - - test("Date", () => { - const date: Date = new Date("2018-05-01T00:00:00"); - testParse(`db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": Date("${date.toUTCString()}") });`, { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: date.toString() - }, - name: "Stephen" - } - ] - }); - }); - - test("Keys with periods", () => { - testParse( - `db.timesheets.update( { + { + collection: "c2", + name: "insertMany", + args: [ + [ + { + name: "Stephen", + age: 38, + male: true, + }, + { + name: "Stephen", + age: 38, + male: true, + }, + ], + ], + } + ); + }); + + test("test function call that has 2 arguments", () => { + const arg0 = `{"Age": 31}`; + const arg1 = `{"Name": true}`; + const text = `db.find(${arg0}\r\n,\r\n\r\n${arg1})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); + assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); + }); + test("test function call with nested parameters - documents in an array", () => { + const arg0 = `[{"name": "a"}, {"name": "b"}, {"name": "c"}]`; + const arg1 = `{"ordered": true}`; + const text = `db.test1.insertMany(${arg0},\r\n\r\n\r\n${arg1})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); + assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); + }); + test("test function call that has a nested parameter", () => { + const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; + const text = `db.test1.insertMany(${arg0})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); + }); + test("test function call with erroneous syntax: missing comma", () => { + const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; + const arg1 = `{"ordered": true}`; + const text = `db.test1.insertMany(${arg0} ${arg1})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const err = nonNullProp(command, "errors")[0]; + assert.deepEqual( + err.message, + "mismatched input '{' expecting {',', ')'}" + ); + assert.deepEqual(err.range.start.line, 0); + assert.deepEqual(err.range.start.character, 61); + }); + test("test function call with erroneous syntax: missing comma, parameters separated with newline", () => { + const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; + const arg1 = `{"ordered": \ntrue}`; + const text = `db.test1.insertMany(${arg0} \n ${arg1})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const err = nonNullProp(command, "errors")[0]; + assert.deepEqual( + err.message, + "mismatched input '{' expecting {',', ')'}" + ); + assert.deepEqual(err.range.start.line, 1); + assert.deepEqual(err.range.start.character, 2); + }); + test("test function call with erroneous syntax: missing double quote", () => { + const text = `db.test1.insertMany({name": {"First" : "a", "Last":"b"} })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const err = nonNullProp(command, "errors")[0]; + assert.deepEqual(err.message, "missing ':' at '\": {\"'"); + assert.deepEqual(err.range.start.line, 0); + assert.deepEqual(err.range.start.character, 25); + }); + test("test function call with erroneous syntax: missing opening brace", () => { + const text = `db.test1.insertMany("name": {"First" : "a", "Last":"b"} })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const err = nonNullProp(command, "errors")[0]; + assert.deepEqual( + err.message, + "mismatched input ':' expecting {',', ')'}" + ); + assert.deepEqual(err.range.start.line, 0); + assert.deepEqual(err.range.start.character, 26); + }); + + test("Chained command: to use pretty()", () => { + testParse("db.timesheets.find().pretty();", { + collection: "timesheets", + name: "pretty", + args: [], + }); + }); + + test("ISODate with standard date string", () => { + testParse( + 'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00Z") });', + { + collection: "c1", + name: "insertOne", + args: [ + { + _id: { + $oid: "5aecf1a63d8af732f07e4275", + }, + date: { + $date: "2018-05-01T00:00:00.000Z", + }, + name: "Stephen", + }, + ], + } + ); + }); + + test("ISODate without Z in date string", () => { + testParse( + 'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00") });', + { + collection: "c1", + name: "insertOne", + args: [ + { + _id: { + $oid: "5aecf1a63d8af732f07e4275", + }, + date: { + $date: "2018-05-01T00:00:00.000Z", + }, + name: "Stephen", + }, + ], + } + ); + }); + + test("Invalid ISODate", () => { + testParse( + 'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00z") });', + { + collection: "c1", + name: "insertOne", + args: [], + firstErrorText: "Invalid time value", + } + ); + }); + + test("Date", () => { + const date: Date = new Date("2018-05-01T00:00:00"); + testParse( + `db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": Date("${date.toUTCString()}") });`, + { + collection: "c1", + name: "insertOne", + args: [ + { + _id: { + $oid: "5aecf1a63d8af732f07e4275", + }, + date: { + $date: date.toString(), + }, + name: "Stephen", + }, + ], + } + ); + }); + + test("Keys with periods", () => { + testParse( + `db.timesheets.update( { "year":"2018", "month":"06" },{ @@ -547,592 +652,898 @@ suite("scrapbook parsing Tests", () => { } }); `, - { - collection: "timesheets", - name: "update", - args: [ - { - year: 2018, - month: "06" - }, - { - $set: { - "workers.0.days.0.something": "yupy!" - } - } - ] - }); - }); - - test("nested objects", () => { - testParse( - `db.users.update({},{ + { + collection: "timesheets", + name: "update", + args: [ + { + year: 2018, + month: "06", + }, + { + $set: { + "workers.0.days.0.something": "yupy!", + }, + }, + ], + } + ); + }); + + test("nested objects", () => { + testParse( + `db.users.update({},{ "$pull":{ "proposals":{ "$elemMatch":{"_id":"4qsBHLDCb755c3vPH"} } } })`, - { - collection: "users", - name: "update", - args: [ - {}, - { - $pull: { - proposals: { - $elemMatch: { - _id: "4qsBHLDCb755c3vPH" - } - } - } - } - ] - }); - }); - test("test function call with and without quotes", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.test1.insertMany({${wrapInQuotes("name", q)}: 'First' })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "First" }]); - } - }); - test("test function call with numbers", () => { - const text = `db.test1.insertMany({'name': 1010101})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: 1010101 }]); - }); - test("test function call boolean", () => { - const text = `db.test1.insertMany({'name': false})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: false }]); - }); - test("test function call token inside quotes", () => { - const text = `db.test1.insertMany({'name': 'false'})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "false" }]); - }); - test("test function call with an empty string property value", () => { - const text = `db.test1.insertMany({'name': ''})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "" }]); - }); - test("test function call with array and multiple arguments", () => { - const text = `db.test1.find({'roles': ['readWrite', 'dbAdmin']}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ roles: ["readWrite", "dbAdmin"] }, { resources: ["secondary", "primary"] }]); - }); - test("test function call with nested objects", () => { - const text = `db.test1.find({'roles': [{'optional': 'yes'}]}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ roles: [{ optional: "yes" }] }, { resources: ["secondary", "primary"] }]); - }); - - test("test incomplete function call - replicate user typing - no function call yet", () => { - const text = `db.test1.`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, []); - assert.deepEqual(command.collection, "test1"); - }); - - test("test incomplete function call - replicate user typing - missing propertyValue", () => { - const text = `db.test1.find({"name": {"First" : } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test("test incomplete function call - replicate user typing - missing colon & propertyValue", () => { - const text = `db.test1.find({"name": {"First" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test("test incomplete function call - replicate user typing - empty array as argument", () => { - const text = `db.heroes.aggregate([\n])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [[]]); - }); - - test("test quotes inside a string - 1", () => { - const text = `db.test1.find("That's all")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That's all"]); - }); - - test("test quotes inside a string - 2", () => { - const text = `db.test1.find('That"s all')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That\"s all"]); - }); - - // Note: when escaping a character, escape it twice. - test("test quotes inside a string - 3", () => { - const text = `db.test1.find("Hello \\"there\\"")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ['Hello \\"there\\"']); - }); - - test("test quotes inside a string - 4", () => { - const text = `db.test1.find('Hello \\'there\\'')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["Hello \\'there\\'"]); - }); - - test("test nested property names (has dots in the name)", () => { - const text = `db.test1.find({"name.FirstName": 1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ "name.FirstName": 1 }]); - }); - - test("test managed namespace collection names (has dots in the name)", () => { - const text = `db.test1.beep.find({})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "test1.beep"); - }); - - test("test aggregate query", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.orders.aggregate([ - { ${wrapInQuotes("$match", q)}: { ${wrapInQuotes("status", q)} : "A" } }, - { ${wrapInQuotes("$group", q)}: { ${wrapInQuotes("_id", q)}: "$cust_id", ${wrapInQuotes("total", q)}: { ${wrapInQuotes("$sum", q)}: "$amount" } } }, - { ${wrapInQuotes("$sort", q)}: { ${wrapInQuotes("total", q)}: -1 } } + { + collection: "users", + name: "update", + args: [ + {}, + { + $pull: { + proposals: { + $elemMatch: { + _id: "4qsBHLDCb755c3vPH", + }, + }, + }, + }, + ], + } + ); + }); + test("test function call with and without quotes", () => { + for (let q = 0; q <= 2; q++) { + const text = `db.test1.insertMany({${wrapInQuotes( + "name", + q + )}: 'First' })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: "First" }]); + } + }); + test("test function call with numbers", () => { + const text = `db.test1.insertMany({'name': 1010101})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: 1010101 }]); + }); + test("test function call boolean", () => { + const text = `db.test1.insertMany({'name': false})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: false }]); + }); + test("test function call token inside quotes", () => { + const text = `db.test1.insertMany({'name': 'false'})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: "false" }]); + }); + test("test function call with an empty string property value", () => { + const text = `db.test1.insertMany({'name': ''})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: "" }]); + }); + test("test function call with array and multiple arguments", () => { + const text = `db.test1.find({'roles': ['readWrite', 'dbAdmin']}, {'resources': ['secondary', 'primary']})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [ + { roles: ["readWrite", "dbAdmin"] }, + { resources: ["secondary", "primary"] }, + ]); + }); + test("test function call with nested objects", () => { + const text = `db.test1.find({'roles': [{'optional': 'yes'}]}, {'resources': ['secondary', 'primary']})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [ + { roles: [{ optional: "yes" }] }, + { resources: ["secondary", "primary"] }, + ]); + }); + + test("test incomplete function call - replicate user typing - no function call yet", () => { + const text = `db.test1.`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, []); + assert.deepEqual(command.collection, "test1"); + }); + + test("test incomplete function call - replicate user typing - missing propertyValue", () => { + const text = `db.test1.find({"name": {"First" : } })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); + }); + + test("test incomplete function call - replicate user typing - missing colon & propertyValue", () => { + const text = `db.test1.find({"name": {"First" } })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); + }); + + test("test incomplete function call - replicate user typing - empty array as argument", () => { + const text = `db.heroes.aggregate([\n])`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [[]]); + }); + + test("test quotes inside a string - 1", () => { + const text = `db.test1.find("That's all")`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, ["That's all"]); + }); + + test("test quotes inside a string - 2", () => { + const text = `db.test1.find('That"s all')`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, ['That"s all']); + }); + + // Note: when escaping a character, escape it twice. + test("test quotes inside a string - 3", () => { + const text = `db.test1.find("Hello \\"there\\"")`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, ['Hello \\"there\\"']); + }); + + test("test quotes inside a string - 4", () => { + const text = `db.test1.find('Hello \\'there\\'')`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, ["Hello \\'there\\'"]); + }); + + test("test nested property names (has dots in the name)", () => { + const text = `db.test1.find({"name.FirstName": 1})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.argumentObjects, [{ "name.FirstName": 1 }]); + }); + + test("test managed namespace collection names (has dots in the name)", () => { + const text = `db.test1.beep.find({})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "test1.beep"); + }); + + test("test aggregate query", () => { + for (let q = 0; q <= 2; q++) { + const text = `db.orders.aggregate([ + { ${wrapInQuotes("$match", q)}: { ${wrapInQuotes( + "status", + q + )} : "A" } }, + { ${wrapInQuotes("$group", q)}: { ${wrapInQuotes( + "_id", + q + )}: "$cust_id", ${wrapInQuotes("total", q)}: { ${wrapInQuotes( + "$sum", + q + )}: "$amount" } } }, + { ${wrapInQuotes("$sort", q)}: { ${wrapInQuotes( + "total", + q + )}: -1 } } ], { - ${wrapInQuotes("cursor", q)}: { ${wrapInQuotes("batchSize", q)}: 0 } + ${wrapInQuotes("cursor", q)}: { ${wrapInQuotes( + "batchSize", + q + )}: 0 } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "orders"); - assert.deepEqual(command.argumentObjects, [[ - { $match: { status: "A" } }, - { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, - { $sort: { total: -1 } } - ], - { - cursor: { batchSize: 0 } - }]); - } - }); - - test("test ObjectID - no parameter", () => { - const text = `db.c1.insert({"name": ObjectId()})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - assert.ok((nonNullProp(command, 'argumentObjects')[0]).name instanceof ObjectID); - }); - - test("test ObjectID - hex", () => { - const idParam = "abcdef123456789012345678"; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - const id = new ObjectID(idParam); - assert.deepEqual(command.argumentObjects, [{ name: id }]); - }); - - test("test faulty ObjectID - hex - extra characters", () => { - const idParam = "abcdef12345678901234567890"; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const errorMessage = "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, errorMessage); - }); - - test("test faulty ObjectID - hex - fewer characters", () => { - const idParam = "abcdef123456789012345"; - for (let i = 1; i < 3; i++) { - const text = `db.c1.insert({"name": ObjectId(${wrapInQuotes(idParam, i)})})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const errorMessage = "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, errorMessage); - } - }); - //Examples inspired from https://docs.mongodb.com/manual/reference/operator/query/regex/ - test("test regular expressions - only pattern, no flags", () => { - const text = `db.test1.beep.find({ sku: /789$/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, ""); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - pattern and flags", () => { - const text = `db.test1.beep.find({ sku: /789$/i } )`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "i"); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - Intellisense - flag contains invalid option", () => { - const text = `db.test1.beep.find({ sku: /789$/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - const err = parseError(error); - assert.deepEqual("Unexpected node encountered", err.message); - } - }); - - test("test regular expressions - wrong escape - throw error", () => { - const text = `db.test1.beep.find({ sku: /789$\\/b\\/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - assert.equal(error.message, "Invalid regular expression: /789$\\/b\\/: \\ at end of pattern"); - } - }); - - //Passing the following test should imply the rest of the tests pass too. - // The regex parsing tests following this test should help zero-in on which case isn't handled properly. - test("test regular expression parsing - with many special cases", () => { - const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"); - }); - - test("test regular expression parsing EJSON syntax - with many special cases", () => { - const text = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"); - }); - - test("test regular expression parsing interoperability", () => { - const text1 = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"]); - }); - - test("test regular expression parsing interoperability - word break", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\b/g })`; // equivalent to user typing out /ker\b/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\b", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\b"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\b"]); - }); - - test("test regular expression parsing interoperability - newline", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\n/g })`; // equivalent to user typing out /ker\n/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\n", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\n"]); - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\n"]); - }); - test("test regular expression parsing interoperability - carriage return", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\r/g })`; // equivalent to user typing out /ker\r/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\r", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\r"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\r"]); - }); - - test("test regular expressions - only pattern, no flags", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, ""); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - pattern and flags", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"i" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "i"); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - Intellisense - flag contains invalid option", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"q" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, "Invalid flags supplied to RegExp constructor 'q'"); - assert.deepEqual(nonNullProp(command, 'errors')[0].range.start.character, 19); - }); - - test("test regular expression parsing - with groupings", () => { - const text = `db.test1.beep.find({ sku: /(?:hello)\\3/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(?:hello)\\3"); - }); - - test("test regular expression parsing - with special characters", () => { - const text = `db.test1.beep.find({ sku: /(hello)*(world)?(name)+./g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello)*(world)?(name)+."); - }); - - test("test regular expression parsing - with boundaries", () => { - const text = `db.test1.beep.find({ sku: /^(hello world)[^0-9]|(world\\b)$/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello world)[^0-9]|(world\\b)$"); - }); - - test("test regular expression parsing - with quantifiers", () => { - const text = `db.test1.beep.find({ sku: /(hello)*[^0-9]+|(world){0,2}./g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello)*[^0-9]+|(world){0,2}."); - }); - - test("test regular expression parsing - with conditional", () => { - const text = `db.test1.beep.find({ sku: /(hello?= world)|(world)/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello?= world)|(world)"); - }); - - test("test regular expression parsing - with escaped special characters", () => { - const text = `db.test1.beep.find({ sku: /world\\*\\.\\?\\+/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "world\\*\\.\\?\\+"); - }); - - test("test chained command: argument aggregation", () => { - testParse('db.timesheets.find({name: "Andy", surname: "Jackson"}).pretty();', { - collection: "timesheets", - name: "pretty", - args: [{ name: "Andy", surname: "Jackson" }] - }); - }); - - test("Chained command - order of parsed arguments", () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1}).skip(40);', { - collection: "timesheets", - name: "skip", - args: [{ name: "Andy" }, { age: 1 }, 40] - }); - }); - - test("Chained command - missing period", () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1})skip(40);', { - collection: "timesheets", - name: "sort", - args: [{ name: "Andy" }, { age: 1 }], - firstErrorText: "mismatched input 'skip' expecting " - }); - }); - - test("Chained command - mid-type - missing bracket", () => { - testParse('db.timesheets.find({name:"Andy"}).sort', { - collection: "timesheets", - name: "sort", - args: [{ name: "Andy" }], - firstErrorText: "mismatched input '' expecting '('" - }); - }); - - test("Chained command - mid-type - typed the dot, but not the function call", () => { - testParse('db.timesheets.find({name:"Andy"}).', { - collection: "timesheets", - name: "", - args: [{ name: "Andy" }], - firstErrorText: "mismatched input '' expecting IDENTIFIER" - }); - }); - - //TODO: Tests to simulate cases where the user hasn't completed typing - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/688", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.hdr.aggregate([ + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "orders"); + assert.deepEqual(command.argumentObjects, [ + [ + { $match: { status: "A" } }, + { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, + { $sort: { total: -1 } }, + ], + { + cursor: { batchSize: 0 }, + }, + ]); + } + }); + + test("test ObjectID - no parameter", () => { + const text = `db.c1.insert({"name": ObjectId()})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "c1"); + assert.ok( + (nonNullProp(command, "argumentObjects")[0]).name instanceof + ObjectID + ); + }); + + test("test ObjectID - hex", () => { + const idParam = "abcdef123456789012345678"; + const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "c1"); + const id = new ObjectID(idParam); + assert.deepEqual(command.argumentObjects, [{ name: id }]); + }); + + test("test faulty ObjectID - hex - extra characters", () => { + const idParam = "abcdef12345678901234567890"; + const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const errorMessage = + "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; + assert.deepEqual(command.collection, "c1"); + assert.deepEqual(command.argumentObjects, [{ name: {} }]); + assert.deepEqual( + nonNullProp(command, "errors")[0].message, + errorMessage + ); + }); + + test("test faulty ObjectID - hex - fewer characters", () => { + const idParam = "abcdef123456789012345"; + for (let i = 1; i < 3; i++) { + const text = `db.c1.insert({"name": ObjectId(${wrapInQuotes( + idParam, + i + )})})`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const errorMessage = + "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; + assert.deepEqual(command.collection, "c1"); + assert.deepEqual(command.argumentObjects, [{ name: {} }]); + assert.deepEqual( + nonNullProp(command, "errors")[0].message, + errorMessage + ); + } + }); + //Examples inspired from https://docs.mongodb.com/manual/reference/operator/query/regex/ + test("test regular expressions - only pattern, no flags", () => { + const text = `db.test1.beep.find({ sku: /789$/ })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, ""); + assert.deepEqual(generatedRegExp.source, "789$"); + }); + + test("test regular expressions - pattern and flags", () => { + const text = `db.test1.beep.find({ sku: /789$/i } )`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "i"); + assert.deepEqual(generatedRegExp.source, "789$"); + }); + + test("test regular expressions - Intellisense - flag contains invalid option", () => { + const text = `db.test1.beep.find({ sku: /789$/q })`; + try { + const commands: MongoCommand[] = getAllCommandsFromText(text); + findCommandAtPosition(commands, new Position(0, 0)); + } catch (error) { + const err = parseError(error); + assert.deepEqual("Unexpected node encountered", err.message); + } + }); + + test("test regular expressions - wrong escape - throw error", () => { + const text = `db.test1.beep.find({ sku: /789$\\/b\\/q })`; + try { + const commands: MongoCommand[] = getAllCommandsFromText(text); + findCommandAtPosition(commands, new Position(0, 0)); + } catch (error) { + assert.equal( + error.message, + "Invalid regular expression: /789$\\/b\\/: \\ at end of pattern" + ); + } + }); + + //Passing the following test should imply the rest of the tests pass too. + // The regex parsing tests following this test should help zero-in on which case isn't handled properly. + test("test regular expression parsing - with many special cases", () => { + const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual( + generatedRegExp.source, + "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$" + ); + }); + + test("test regular expression parsing EJSON syntax - with many special cases", () => { + const text = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual( + generatedRegExp.source, + "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$" + ); + }); + + test("test regular expression parsing interoperability", () => { + const text1 = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; + const commands1: MongoCommand[] = getAllCommandsFromText(text1); + const command1: MongoCommand = findCommandAtPosition( + commands1, + new Position(0, 0) + ); + const generatedRegExp1 = (( + nonNullProp(command1, "argumentObjects")[0] + )).sku; + const text2 = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; + const commands2: MongoCommand[] = getAllCommandsFromText(text2); + const command2: MongoCommand = findCommandAtPosition( + commands2, + new Position(0, 0) + ); + const generatedRegExp2 = (( + nonNullProp(command2, "argumentObjects")[0] + )).sku; + assert.deepEqual( + [generatedRegExp1.flags, generatedRegExp1.source], + ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"] + ); + assert.deepEqual( + [generatedRegExp2.flags, generatedRegExp2.source], + ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"] + ); + }); + + test("test regular expression parsing interoperability - word break", () => { + const text1 = `db.test1.beep.find({ sku: /ker\\b/g })`; // equivalent to user typing out /ker\b/ + const commands1: MongoCommand[] = getAllCommandsFromText(text1); + const command1: MongoCommand = findCommandAtPosition( + commands1, + new Position(0, 0) + ); + const generatedRegExp1 = (( + nonNullProp(command1, "argumentObjects")[0] + )).sku; + const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\b", $options: "g"} })`; + const commands2: MongoCommand[] = getAllCommandsFromText(text2); + const command2: MongoCommand = findCommandAtPosition( + commands2, + new Position(0, 0) + ); + const generatedRegExp2 = (( + nonNullProp(command2, "argumentObjects")[0] + )).sku; + assert.deepEqual( + [generatedRegExp1.flags, generatedRegExp1.source], + ["g", "ker\\b"] + ); + assert.deepEqual( + [generatedRegExp2.flags, generatedRegExp2.source], + ["g", "ker\\b"] + ); + }); + + test("test regular expression parsing interoperability - newline", () => { + const text1 = `db.test1.beep.find({ sku: /ker\\n/g })`; // equivalent to user typing out /ker\n/ + const commands1: MongoCommand[] = getAllCommandsFromText(text1); + const command1: MongoCommand = findCommandAtPosition( + commands1, + new Position(0, 0) + ); + const generatedRegExp1 = (( + nonNullProp(command1, "argumentObjects")[0] + )).sku; + const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\n", $options: "g"} })`; + const commands2: MongoCommand[] = getAllCommandsFromText(text2); + const command2: MongoCommand = findCommandAtPosition( + commands2, + new Position(0, 0) + ); + const generatedRegExp2 = (( + nonNullProp(command2, "argumentObjects")[0] + )).sku; + assert.deepEqual( + [generatedRegExp2.flags, generatedRegExp2.source], + ["g", "ker\\n"] + ); + assert.deepEqual( + [generatedRegExp1.flags, generatedRegExp1.source], + ["g", "ker\\n"] + ); + }); + test("test regular expression parsing interoperability - carriage return", () => { + const text1 = `db.test1.beep.find({ sku: /ker\\r/g })`; // equivalent to user typing out /ker\r/ + const commands1: MongoCommand[] = getAllCommandsFromText(text1); + const command1: MongoCommand = findCommandAtPosition( + commands1, + new Position(0, 0) + ); + const generatedRegExp1 = (( + nonNullProp(command1, "argumentObjects")[0] + )).sku; + const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\r", $options: "g"} })`; + const commands2: MongoCommand[] = getAllCommandsFromText(text2); + const command2: MongoCommand = findCommandAtPosition( + commands2, + new Position(0, 0) + ); + const generatedRegExp2 = (( + nonNullProp(command2, "argumentObjects")[0] + )).sku; + assert.deepEqual( + [generatedRegExp1.flags, generatedRegExp1.source], + ["g", "ker\\r"] + ); + assert.deepEqual( + [generatedRegExp2.flags, generatedRegExp2.source], + ["g", "ker\\r"] + ); + }); + + test("test regular expressions - only pattern, no flags", () => { + const text = `db.test1.beep.find({ sku: { $regex: "789$" } })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, ""); + assert.deepEqual(generatedRegExp.source, "789$"); + }); + + test("test regular expressions - pattern and flags", () => { + const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"i" } })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "i"); + assert.deepEqual(generatedRegExp.source, "789$"); + }); + + test("test regular expressions - Intellisense - flag contains invalid option", () => { + const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"q" } })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual( + nonNullProp(command, "errors")[0].message, + "Invalid flags supplied to RegExp constructor 'q'" + ); + assert.deepEqual( + nonNullProp(command, "errors")[0].range.start.character, + 19 + ); + }); + + test("test regular expression parsing - with groupings", () => { + const text = `db.test1.beep.find({ sku: /(?:hello)\\3/g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual(generatedRegExp.source, "(?:hello)\\3"); + }); + + test("test regular expression parsing - with special characters", () => { + const text = `db.test1.beep.find({ sku: /(hello)*(world)?(name)+./g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual(generatedRegExp.source, "(hello)*(world)?(name)+."); + }); + + test("test regular expression parsing - with boundaries", () => { + const text = `db.test1.beep.find({ sku: /^(hello world)[^0-9]|(world\\b)$/g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual( + generatedRegExp.source, + "^(hello world)[^0-9]|(world\\b)$" + ); + }); + + test("test regular expression parsing - with quantifiers", () => { + const text = `db.test1.beep.find({ sku: /(hello)*[^0-9]+|(world){0,2}./g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual( + generatedRegExp.source, + "(hello)*[^0-9]+|(world){0,2}." + ); + }); + + test("test regular expression parsing - with conditional", () => { + const text = `db.test1.beep.find({ sku: /(hello?= world)|(world)/g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual(generatedRegExp.source, "(hello?= world)|(world)"); + }); + + test("test regular expression parsing - with escaped special characters", () => { + const text = `db.test1.beep.find({ sku: /world\\*\\.\\?\\+/g })`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + const generatedRegExp = (( + nonNullProp(command, "argumentObjects")[0] + )).sku; + assert.deepEqual(generatedRegExp.flags, "g"); + assert.deepEqual(generatedRegExp.source, "world\\*\\.\\?\\+"); + }); + + test("test chained command: argument aggregation", () => { + testParse( + 'db.timesheets.find({name: "Andy", surname: "Jackson"}).pretty();', + { + collection: "timesheets", + name: "pretty", + args: [{ name: "Andy", surname: "Jackson" }], + } + ); + }); + + test("Chained command - order of parsed arguments", () => { + testParse( + 'db.timesheets.find({name:"Andy"}).sort({age: 1}).skip(40);', + { + collection: "timesheets", + name: "skip", + args: [{ name: "Andy" }, { age: 1 }, 40], + } + ); + }); + + test("Chained command - missing period", () => { + testParse('db.timesheets.find({name:"Andy"}).sort({age: 1})skip(40);', { + collection: "timesheets", + name: "sort", + args: [{ name: "Andy" }, { age: 1 }], + firstErrorText: "mismatched input 'skip' expecting ", + }); + }); + + test("Chained command - mid-type - missing bracket", () => { + testParse('db.timesheets.find({name:"Andy"}).sort', { + collection: "timesheets", + name: "sort", + args: [{ name: "Andy" }], + firstErrorText: "mismatched input '' expecting '('", + }); + }); + + test("Chained command - mid-type - typed the dot, but not the function call", () => { + testParse('db.timesheets.find({name:"Andy"}).', { + collection: "timesheets", + name: "", + args: [{ name: "Andy" }], + firstErrorText: "mismatched input '' expecting IDENTIFIER", + }); + }); + + //TODO: Tests to simulate cases where the user hasn't completed typing + + test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/688", () => { + for (let q = 0; q <= 2; q++) { + const text = `db.hdr.aggregate([ { ${wrapInQuotes("$match", q)}: { "CURRENCY_ID": "USD" } }, ])`; //Note the trailing comma. There should be 1 argument object returned, an array, that has 2 elements - //one expected, and another empty object. - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "hdr"); - assert.deepEqual(command.argumentObjects, [[{ $match: { CURRENCY_ID: "USD" } }, {}]]); - } - }); - - test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/785", () => { - testParse('db.timesheets.find({name:"Andy"}).count();', { - collection: "timesheets", - name: "count", - args: [{ name: "Andy" }] - }); - }); - - test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/795", () => { - testParse('db.timesheets.find({}).limit(10);', { - collection: "timesheets", - name: "limit", - args: [{}, 10] - }); - }); - - test("Chained command alternative for rs.slaveOk()- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/565", () => { - testParse('db.getMongo().setSlaveOk();', { - collection: "", - name: "setSlaveOk", - args: [] - }); - }); - - test("Multiple line command, from #489", () => { - testParse( - ` + //one expected, and another empty object. + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "hdr"); + assert.deepEqual(command.argumentObjects, [ + [{ $match: { CURRENCY_ID: "USD" } }, {}], + ]); + } + }); + + test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/785", () => { + testParse('db.timesheets.find({name:"Andy"}).count();', { + collection: "timesheets", + name: "count", + args: [{ name: "Andy" }], + }); + }); + + test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/795", () => { + testParse("db.timesheets.find({}).limit(10);", { + collection: "timesheets", + name: "limit", + args: [{}, 10], + }); + }); + + test("Chained command alternative for rs.slaveOk()- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/565", () => { + testParse("db.getMongo().setSlaveOk();", { + collection: "", + name: "setSlaveOk", + args: [], + }); + }); + + test("Multiple line command, from #489", () => { + testParse( + ` db.finalists.find({name: "Jefferson"}) . limit (10); `, - { - collection: "finalists", - name: "limit", - args: [ - { - name: "Jefferson" - }, - 10 - ] - }); - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/703", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({ ${wrapInQuotes("user", q)}: { ${wrapInQuotes("$in", q)}: [ "A80", "HPA" ] } },{ ${wrapInQuotes("_id", q)}: false });`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "Users"); - assert.deepEqual(command.argumentObjects, [{ user: { $in: ["A80", "HPA"] } }, { _id: false }]); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/691", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.users.aggregate([ - { ${wrapInQuotes("$match", q)}: {${wrapInQuotes("_id", q)}: {"$oid" :"5b23d2ba92b52cf794bdeb9c")}}}, + { + collection: "finalists", + name: "limit", + args: [ + { + name: "Jefferson", + }, + 10, + ], + } + ); + }); + + test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/703", () => { + for (let q = 0; q <= 2; q++) { + const text = `db.Users.find({ ${wrapInQuotes( + "user", + q + )}: { ${wrapInQuotes( + "$in", + q + )}: [ "A80", "HPA" ] } },{ ${wrapInQuotes("_id", q)}: false });`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "Users"); + assert.deepEqual(command.argumentObjects, [ + { user: { $in: ["A80", "HPA"] } }, + { _id: false }, + ]); + } + }); + + test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/691", () => { + for (let q = 0; q <= 2; q++) { + const text = `db.users.aggregate([ + { ${wrapInQuotes("$match", q)}: {${wrapInQuotes( + "_id", + q + )}: {"$oid" :"5b23d2ba92b52cf794bdeb9c")}}}, { ${wrapInQuotes("$project", q)}: { - ${wrapInQuotes("scores", q)}: {${wrapInQuotes("$filter", q)}: { + ${wrapInQuotes("scores", q)}: {${wrapInQuotes( + "$filter", + q + )}: { ${wrapInQuotes("input", q)}: '$scores', ${wrapInQuotes("as", q)}: 'score', - ${wrapInQuotes("cond", q)}: {${wrapInQuotes("$gt", q)}: ['$$score', 3]} + ${wrapInQuotes("cond", q)}: {${wrapInQuotes( + "$gt", + q + )}: ['$$score', 3]} }} }} ])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "users"); - assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][0], { $match: { _id: new ObjectId("5b23d2ba92b52cf794bdeb9c") } }); - assert.deepEqual( - nonNullProp(command, 'argumentObjects')[0][1], - { - $project: { - scores: { - $filter: { - input: '$scores', - as: 'score', - cond: { $gt: ['$$score', 3] } - } - } - } - }); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/717", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({${wrapInQuotes("age", q)} : { ${wrapInQuotes("$in", q)} : [19, 20, 22, 25]}});`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "Users"); - assert.deepEqual(command.argumentObjects, [{ age: { $in: [19, 20, 22, 25] } }]); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/737", () => { - const text = `db.c1.insert({},f)`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{}, {}]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, "mismatched input 'f' expecting {'{', '[', RegexLiteral, StringLiteral, 'null', BooleanLiteral, NumericLiteral}"); - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/899 - multi-line comment, not regex", () => { - for (const escape of ['\n', '\r', '\n\r', '\r\n']) { - const text = `db.heroes.count()${escape}/*db.c2.insertMany([${escape}{"name": "Stephen", "age": 38, "male": true},${escape}{"name": "Stephen", "age": 38, "male": true}${escape}]);${escape}*/${escape}${escape}db.heroes.find();`; - const commands = getAllCommandsFromText(text); - assert.equal(commands.length, 2, `Error in parsing ${text}`); - assert.equal(commands[0].name, "count"); - assert.equal(commands[1].name, "find"); - } - }); + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "users"); + assert.deepEqual(nonNullProp(command, "argumentObjects")[0][0], { + $match: { _id: new ObjectId("5b23d2ba92b52cf794bdeb9c") }, + }); + assert.deepEqual(nonNullProp(command, "argumentObjects")[0][1], { + $project: { + scores: { + $filter: { + input: "$scores", + as: "score", + cond: { $gt: ["$$score", 3] }, + }, + }, + }, + }); + } + }); + + test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/717", () => { + for (let q = 0; q <= 2; q++) { + const text = `db.Users.find({${wrapInQuotes( + "age", + q + )} : { ${wrapInQuotes("$in", q)} : [19, 20, 22, 25]}});`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "Users"); + assert.deepEqual(command.argumentObjects, [ + { age: { $in: [19, 20, 22, 25] } }, + ]); + } + }); + + test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/737", () => { + const text = `db.c1.insert({},f)`; + const commands: MongoCommand[] = getAllCommandsFromText(text); + const command: MongoCommand = findCommandAtPosition( + commands, + new Position(0, 0) + ); + assert.deepEqual(command.collection, "c1"); + assert.deepEqual(command.argumentObjects, [{}, {}]); + assert.deepEqual( + nonNullProp(command, "errors")[0].message, + "mismatched input 'f' expecting {'{', '[', RegexLiteral, StringLiteral, 'null', BooleanLiteral, NumericLiteral}" + ); + }); + + test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/899 - multi-line comment, not regex", () => { + for (const escape of ["\n", "\r", "\n\r", "\r\n"]) { + const text = `db.heroes.count()${escape}/*db.c2.insertMany([${escape}{"name": "Stephen", "age": 38, "male": true},${escape}{"name": "Stephen", "age": 38, "male": true}${escape}]);${escape}*/${escape}${escape}db.heroes.find();`; + const commands = getAllCommandsFromText(text); + assert.equal(commands.length, 2, `Error in parsing ${text}`); + assert.equal(commands[0].name, "count"); + assert.equal(commands[1].name, "find"); + } + }); }); diff --git a/test/mongoShell.test.ts b/test/mongoShell.test.ts index 83fdb845e..563495cc3 100644 --- a/test/mongoShell.test.ts +++ b/test/mongoShell.test.ts @@ -4,285 +4,348 @@ *--------------------------------------------------------------------------------------------*/ // CONSIDER: Run in pipeline -import * as assert from 'assert'; +import * as assert from "assert"; import * as cp from "child_process"; -import * as fse from 'fs-extra'; -import * as os from 'os'; -import * as path from 'path'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { ext, IDisposable, isWindows, MongoShell, parseError } from '../extension.bundle'; -import { runWithSetting } from './runWithSetting'; -import { setEnvironmentVariables } from './util/setEnvironmentVariables'; +import * as fse from "fs-extra"; +import * as os from "os"; +import * as path from "path"; +import { isNumber } from "util"; +import * as vscode from "vscode"; +import { + ext, + IDisposable, + isWindows, + MongoShell, + parseError, +} from "../extension.bundle"; +import { runWithSetting } from "./runWithSetting"; +import { setEnvironmentVariables } from "./util/setEnvironmentVariables"; const VERBOSE = false; // If true, the output from the Mongo server and shell will be sent to the console for debugging purposes let testsSupported: boolean = true; if (!isWindows) { - // CONSIDER: Non-Windows - console.warn(`Not running in Windows - skipping MongoShell tests`); - testsSupported = false; + // CONSIDER: Non-Windows + console.warn(`Not running in Windows - skipping MongoShell tests`); + testsSupported = false; } suite("MongoShell", async function (this: Mocha.Suite): Promise { - // https://github.com/mochajs/mocha/issues/2025 - this.timeout(10000); - - async function testIfSupported(title: string, fn?: Mocha.Func | Mocha.AsyncFunc): Promise { - await runWithSetting(ext.settingsKeys.mongoShellTimeout, '60', async () => { - if (testsSupported) { - test(title, fn); - } else { - test(title); - } - }); - } - - // CONSIDER: Make more generic - let mongodCP: cp.ChildProcess; - const mongodPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongod.exe"; - const mongoPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongo.exe"; - let mongoDOutput = ""; - let mongoDErrors = ""; - let isClosed = false; - - if (!fse.existsSync(mongodPath)) { - console.log(`Couldn't find mongod.exe at ${mongodPath} - skipping MongoShell tests`); - testsSupported = false; - } else if (!fse.existsSync(mongodPath)) { - console.log(`Couldn't find mongo.exe at ${mongoPath} - skipping MongoShell tests`); - testsSupported = false; - } else { - // Prevent code 100 error: https://stackoverflow.com/questions/41420466/mongodb-shuts-down-with-code-100 - await fse.ensureDir('D:\\data\\db\\'); - } - - class FakeOutputChannel implements vscode.OutputChannel { - public name: string; - public output: string; - - public append(value: string): void { - assert(value !== undefined); - assert(!value.includes('undefined')); - this.output = this.output ? this.output + os.EOL + value : value; - log(value, "Output channel: "); - } - public appendLine(value: string): void { - assert(value !== undefined); - this.append(value + os.EOL); - } - public clear(): void { } - public show(preserveFocus?: boolean): void; - public show(column?: vscode.ViewColumn, preserveFocus?: boolean): void; - public show(_column?: any, _preserveFocus?: any): void { } - public hide(): void { } - public dispose(): void { } - public replace(_value: string): void { } - } - - function log(text: string, linePrefix: string): void { - text = text.replace(/(^|[\r\n]+)/g, "$1" + linePrefix); - if (VERBOSE) { - console.log(text); - } - } - - async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); - } - - function executeInShell(command: string): string { - return cp.execSync(command, {}).toString(); - } - - suiteSetup(() => { - if (testsSupported) { - assert(fse.existsSync(mongodPath), "Couldn't find mongod.exe at " + mongodPath); - assert(fse.existsSync(mongoPath), "Couldn't find mongo.exe at " + mongoPath); - - // Shut down any still-running mongo server - try { - executeInShell('taskkill /f /im mongod.exe'); - } catch (error) { - assert(/The process .* not found/.test(parseError(error).message), `Error killing mongod: ${parseError(error).message}`); - } - - mongodCP = cp.spawn(mongodPath, ['--quiet']); - - mongodCP.stdout?.on("data", (buffer: Buffer) => { - log(buffer.toString(), "mongo server: "); - mongoDOutput += buffer.toString(); - }); - mongodCP.stderr?.on("data", (buffer: Buffer) => { - log(buffer.toString(), "mongo server STDERR: "); - mongoDErrors += buffer.toString(); - }); - mongodCP.on("error", (error: unknown) => { - log(parseError(error).message, "mongo server Error: "); - mongoDErrors += parseError(error).message + os.EOL; - }); - mongodCP.on("close", (code?: number) => { - console.log(`mongo server: Close code=${code}`); - isClosed = true; - if (isNumber(code) && code !== 0) { - mongoDErrors += `mongo server: Closed with code "${code}"${os.EOL}`; - } - }); - } - }); - - suiteTeardown(() => { - if (mongodCP) { - mongodCP.kill(); - } - }); - - await testIfSupported("Verify mongod running", async () => { - while (!mongoDOutput.includes('waiting for connections on port 27017')) { - assert.equal(mongoDErrors, "", "Expected no errors"); - assert(!isClosed); - await delay(50); - } - }); - - async function testShellCommand(options: { - script: string; - expectedResult?: string; - expectedError?: string | RegExp; - expectedOutput?: RegExp; - title?: string; // Defaults to script - args?: string[]; // Defaults to [] - mongoPath?: string; // Defaults to the correct mongo path - env?: { [key: string]: string }; // Add to environment - timeoutSeconds?: number; - }): Promise { - await testIfSupported(options.title || options.script, async () => { - assert(!isClosed); - assert(mongoDErrors === ""); - - let previousEnv: IDisposable | undefined; - let shell: MongoShell | undefined; - const outputChannel = new FakeOutputChannel(); - - try { - previousEnv = setEnvironmentVariables(options.env || {}); - shell = await MongoShell.create(options.mongoPath || mongoPath, options.args || [], '', false, outputChannel, options.timeoutSeconds || 5); - const result = await shell.executeScript(options.script); - if (options.expectedError) { - assert(false, `Expected error did not occur: '${options.expectedError}'`); - } - if (options.expectedResult !== undefined) { - assert.equal(result, options.expectedResult); - } - } catch (error) { - const message = parseError(error).message; - - if (options.expectedError instanceof RegExp) { - assert(options.expectedError.test(message), `Actual error did not match expected error regex. Actual error: ${message}`); - } else if (typeof options.expectedError === 'string') { - assert.equal(message, options.expectedError); - } else { - assert(false, `Unexpected error during the test: ${message}`); - } - - if (options.expectedOutput instanceof RegExp) { - assert(options.expectedOutput.test(outputChannel.output), `Actual contents written to output channel did not match expected regex. Actual output channel contents: ${outputChannel.output}`); - } - } finally { - if (shell) { - shell.dispose(); - } - if (previousEnv) { - previousEnv.dispose(); - } - } - }); - } - - await testShellCommand({ - script: 'use abc', - expectedResult: 'switched to db abc' - }); - - await testShellCommand({ - title: "Incorrect path", - script: 'use abc', - mongoPath: "/notfound/mongo.exe", - expectedError: /Could not find .*notfound.*mongo.exe/ - }); - - await testShellCommand({ - title: "Find mongo through PATH", - script: 'use abc', - mongoPath: "mongo", - expectedResult: 'switched to db abc', - env: { - PATH: process.env.path! + ";" + path.dirname(mongoPath) - } - }); - - await testShellCommand({ - title: "With valid argument", - script: 'use abc', - args: ["--quiet"], - expectedResult: 'switched to db abc' - }); - - await testShellCommand({ - title: "With invalid argument", - script: '', - args: ["--hey-man-how-are-you"], - expectedError: /Error parsing command line: unrecognised option/ - }); - - await testShellCommand({ - title: "Output window may contain additional information", - script: '', - args: ["-u", "baduser", "-p", "badpassword"], - expectedError: /The output window may contain additional information/ - }); - - await testShellCommand({ - title: "With bad credentials", - script: '', - args: ["-u", "baduser", "-p", "badpassword"], - expectedError: /The process exited with code 1/, - expectedOutput: /Authentication failed/ - }); - - await testShellCommand({ - title: "Process exits immediately", - script: '', - args: ["--version"], - expectedError: /The process exited prematurely/ - }); - - await testShellCommand({ - title: "Javascript", - script: "for (var i = 0; i < 123; ++i) { }; i", - expectedResult: "123" - }); - - await testShellCommand({ - title: "Actual timeout", - script: "for (var i = 0; i < 10000000; ++i) { }; i", - expectedError: /Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting./, - timeoutSeconds: 2 - }); - - await testIfSupported("More results than displayed (type 'it' for more -> (More))", async () => { - const shell = await MongoShell.create(mongoPath, [], '', false, new FakeOutputChannel(), 5); - await shell.executeScript('db.mongoShellTest.drop()'); - await shell.executeScript('for (var i = 0; i < 50; ++i) { db.mongoShellTest.insert({a:i}); }'); - - const result = await shell.executeScript('db.mongoShellTest.find().pretty()'); - - assert(!result.includes('Type "it" for more')); - assert(result.includes('(More)')); - - shell.dispose(); - }); + // https://github.com/mochajs/mocha/issues/2025 + this.timeout(10000); + + async function testIfSupported( + title: string, + fn?: Mocha.Func | Mocha.AsyncFunc + ): Promise { + await runWithSetting( + ext.settingsKeys.mongoShellTimeout, + "60", + async () => { + if (testsSupported) { + test(title, fn); + } else { + test(title); + } + } + ); + } + + // CONSIDER: Make more generic + let mongodCP: cp.ChildProcess; + const mongodPath = + "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongod.exe"; + const mongoPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongo.exe"; + let mongoDOutput = ""; + let mongoDErrors = ""; + let isClosed = false; + + if (!fse.existsSync(mongodPath)) { + console.log( + `Couldn't find mongod.exe at ${mongodPath} - skipping MongoShell tests` + ); + testsSupported = false; + } else if (!fse.existsSync(mongodPath)) { + console.log( + `Couldn't find mongo.exe at ${mongoPath} - skipping MongoShell tests` + ); + testsSupported = false; + } else { + // Prevent code 100 error: https://stackoverflow.com/questions/41420466/mongodb-shuts-down-with-code-100 + await fse.ensureDir("D:\\data\\db\\"); + } + + class FakeOutputChannel implements vscode.OutputChannel { + public name: string; + public output: string; + + public append(value: string): void { + assert(value !== undefined); + assert(!value.includes("undefined")); + this.output = this.output ? this.output + os.EOL + value : value; + log(value, "Output channel: "); + } + public appendLine(value: string): void { + assert(value !== undefined); + this.append(value + os.EOL); + } + public clear(): void {} + public show(preserveFocus?: boolean): void; + public show(column?: vscode.ViewColumn, preserveFocus?: boolean): void; + public show(_column?: any, _preserveFocus?: any): void {} + public hide(): void {} + public dispose(): void {} + public replace(_value: string): void {} + } + + function log(text: string, linePrefix: string): void { + text = text.replace(/(^|[\r\n]+)/g, "$1" + linePrefix); + if (VERBOSE) { + console.log(text); + } + } + + async function delay(milliseconds: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); + } + + function executeInShell(command: string): string { + return cp.execSync(command, {}).toString(); + } + + suiteSetup(() => { + if (testsSupported) { + assert( + fse.existsSync(mongodPath), + "Couldn't find mongod.exe at " + mongodPath + ); + assert( + fse.existsSync(mongoPath), + "Couldn't find mongo.exe at " + mongoPath + ); + + // Shut down any still-running mongo server + try { + executeInShell("taskkill /f /im mongod.exe"); + } catch (error) { + assert( + /The process .* not found/.test(parseError(error).message), + `Error killing mongod: ${parseError(error).message}` + ); + } + + mongodCP = cp.spawn(mongodPath, ["--quiet"]); + + mongodCP.stdout?.on("data", (buffer: Buffer) => { + log(buffer.toString(), "mongo server: "); + mongoDOutput += buffer.toString(); + }); + mongodCP.stderr?.on("data", (buffer: Buffer) => { + log(buffer.toString(), "mongo server STDERR: "); + mongoDErrors += buffer.toString(); + }); + mongodCP.on("error", (error: unknown) => { + log(parseError(error).message, "mongo server Error: "); + mongoDErrors += parseError(error).message + os.EOL; + }); + mongodCP.on("close", (code?: number) => { + console.log(`mongo server: Close code=${code}`); + isClosed = true; + if (isNumber(code) && code !== 0) { + mongoDErrors += `mongo server: Closed with code "${code}"${os.EOL}`; + } + }); + } + }); + + suiteTeardown(() => { + if (mongodCP) { + mongodCP.kill(); + } + }); + + await testIfSupported("Verify mongod running", async () => { + while ( + !mongoDOutput.includes("waiting for connections on port 27017") + ) { + assert.equal(mongoDErrors, "", "Expected no errors"); + assert(!isClosed); + await delay(50); + } + }); + + async function testShellCommand(options: { + script: string; + expectedResult?: string; + expectedError?: string | RegExp; + expectedOutput?: RegExp; + title?: string; // Defaults to script + args?: string[]; // Defaults to [] + mongoPath?: string; // Defaults to the correct mongo path + env?: { [key: string]: string }; // Add to environment + timeoutSeconds?: number; + }): Promise { + await testIfSupported(options.title || options.script, async () => { + assert(!isClosed); + assert(mongoDErrors === ""); + + let previousEnv: IDisposable | undefined; + let shell: MongoShell | undefined; + const outputChannel = new FakeOutputChannel(); + + try { + previousEnv = setEnvironmentVariables(options.env || {}); + shell = await MongoShell.create( + options.mongoPath || mongoPath, + options.args || [], + "", + false, + outputChannel, + options.timeoutSeconds || 5 + ); + const result = await shell.executeScript(options.script); + if (options.expectedError) { + assert( + false, + `Expected error did not occur: '${options.expectedError}'` + ); + } + if (options.expectedResult !== undefined) { + assert.equal(result, options.expectedResult); + } + } catch (error) { + const message = parseError(error).message; + + if (options.expectedError instanceof RegExp) { + assert( + options.expectedError.test(message), + `Actual error did not match expected error regex. Actual error: ${message}` + ); + } else if (typeof options.expectedError === "string") { + assert.equal(message, options.expectedError); + } else { + assert( + false, + `Unexpected error during the test: ${message}` + ); + } + + if (options.expectedOutput instanceof RegExp) { + assert( + options.expectedOutput.test(outputChannel.output), + `Actual contents written to output channel did not match expected regex. Actual output channel contents: ${outputChannel.output}` + ); + } + } finally { + if (shell) { + shell.dispose(); + } + if (previousEnv) { + previousEnv.dispose(); + } + } + }); + } + + await testShellCommand({ + script: "use abc", + expectedResult: "switched to db abc", + }); + + await testShellCommand({ + title: "Incorrect path", + script: "use abc", + mongoPath: "/notfound/mongo.exe", + expectedError: /Could not find .*notfound.*mongo.exe/, + }); + + await testShellCommand({ + title: "Find mongo through PATH", + script: "use abc", + mongoPath: "mongo", + expectedResult: "switched to db abc", + env: { + PATH: process.env.path! + ";" + path.dirname(mongoPath), + }, + }); + + await testShellCommand({ + title: "With valid argument", + script: "use abc", + args: ["--quiet"], + expectedResult: "switched to db abc", + }); + + await testShellCommand({ + title: "With invalid argument", + script: "", + args: ["--hey-man-how-are-you"], + expectedError: /Error parsing command line: unrecognised option/, + }); + + await testShellCommand({ + title: "Output window may contain additional information", + script: "", + args: ["-u", "baduser", "-p", "badpassword"], + expectedError: /The output window may contain additional information/, + }); + + await testShellCommand({ + title: "With bad credentials", + script: "", + args: ["-u", "baduser", "-p", "badpassword"], + expectedError: /The process exited with code 1/, + expectedOutput: /Authentication failed/, + }); + + await testShellCommand({ + title: "Process exits immediately", + script: "", + args: ["--version"], + expectedError: /The process exited prematurely/, + }); + + await testShellCommand({ + title: "Javascript", + script: "for (var i = 0; i < 123; ++i) { }; i", + expectedResult: "123", + }); + + await testShellCommand({ + title: "Actual timeout", + script: "for (var i = 0; i < 10000000; ++i) { }; i", + expectedError: + /Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting./, + timeoutSeconds: 2, + }); + + await testIfSupported( + "More results than displayed (type 'it' for more -> (More))", + async () => { + const shell = await MongoShell.create( + mongoPath, + [], + "", + false, + new FakeOutputChannel(), + 5 + ); + await shell.executeScript("db.mongoShellTest.drop()"); + await shell.executeScript( + "for (var i = 0; i < 50; ++i) { db.mongoShellTest.insert({a:i}); }" + ); + + const result = await shell.executeScript( + "db.mongoShellTest.find().pretty()" + ); + + assert(!result.includes('Type "it" for more')); + assert(result.includes("(More)")); + + shell.dispose(); + } + ); }); diff --git a/test/postgresConnectionStrings.test.ts b/test/postgresConnectionStrings.test.ts index 3f2ed8da4..c092b0849 100644 --- a/test/postgresConnectionStrings.test.ts +++ b/test/postgresConnectionStrings.test.ts @@ -3,28 +3,58 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { addDatabaseToConnectionString } from '../extension.bundle'; - -function testAddDatabaseToConectionString(connectionString: string, databaseName: string, expectedConnectionString: string | undefined): void { - const modifiedConnectionString = addDatabaseToConnectionString(connectionString, databaseName); - assert.equal(modifiedConnectionString, expectedConnectionString); +import * as assert from "assert"; +import { addDatabaseToConnectionString } from "../extension.bundle"; + +function testAddDatabaseToConectionString( + connectionString: string, + databaseName: string, + expectedConnectionString: string | undefined +): void { + const modifiedConnectionString = addDatabaseToConnectionString( + connectionString, + databaseName + ); + assert.equal(modifiedConnectionString, expectedConnectionString); } suite(`postgresConnectionStrings`, () => { - test(`addDatabaseToConnectionString`, () => { - // Connection strings follow the following format (https://www.postgresql.org/docs/12/libpq-connect.html): - // postgres://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/`, 'testdb', 'postgres://user:password@test:5432/testdb'); - testAddDatabaseToConectionString(`postgres://user:password@test:5432/testdb`, 'testdb2', `postgres://user:password@test:5432/testdb2`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432`, 'testdb', 'postgres://user:password@test:5432/testdb'); - testAddDatabaseToConectionString(`postgres://user:password@test:5432/?ssl=true&sslmode=require`, 'testdb', `postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`, 'testdb2', `postgres://user:password@test:5432/testdb2?ssl=true&sslmode=require`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/`, `test%20`, `postgres://user:password@test:5432/test%2520`); - - }); + test(`addDatabaseToConnectionString`, () => { + // Connection strings follow the following format (https://www.postgresql.org/docs/12/libpq-connect.html): + // postgres://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] + + testAddDatabaseToConectionString( + `postgres://user:password@test:5432/`, + "testdb", + "postgres://user:password@test:5432/testdb" + ); + testAddDatabaseToConectionString( + `postgres://user:password@test:5432/testdb`, + "testdb2", + `postgres://user:password@test:5432/testdb2` + ); + + testAddDatabaseToConectionString( + `postgres://user:password@test:5432`, + "testdb", + "postgres://user:password@test:5432/testdb" + ); + testAddDatabaseToConectionString( + `postgres://user:password@test:5432/?ssl=true&sslmode=require`, + "testdb", + `postgres://user:password@test:5432/testdb?ssl=true&sslmode=require` + ); + + testAddDatabaseToConectionString( + `postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`, + "testdb2", + `postgres://user:password@test:5432/testdb2?ssl=true&sslmode=require` + ); + + testAddDatabaseToConectionString( + `postgres://user:password@test:5432/`, + `test%20`, + `postgres://user:password@test:5432/test%2520` + ); + }); }); diff --git a/test/runTest.ts b/test/runTest.ts index f4fe5eb12..603ebc81b 100644 --- a/test/runTest.ts +++ b/test/runTest.ts @@ -3,44 +3,52 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron'; -import * as cp from 'child_process'; -import * as path from 'path'; +import { + downloadAndUnzipVSCode, + resolveCliArgsFromVSCodeExecutablePath, + runTests, +} from "@vscode/test-electron"; +import * as cp from "child_process"; +import * as path from "path"; async function main(): Promise { - try { - const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); - const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); + try { + const vscodeExecutablePath = await downloadAndUnzipVSCode("stable"); + const [cli, ...args] = + resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - cp.spawnSync( - cli, - [ - ...args, - '--install-extension', 'ms-vscode.azure-account', - '--install-extension', 'ms-azuretools.vscode-azureresourcegroups', - ], - { - encoding: 'utf-8', - stdio: 'inherit' - }); + cp.spawnSync( + cli, + [ + ...args, + "--install-extension", + "ms-vscode.azure-account", + "--install-extension", + "ms-azuretools.vscode-azureresourcegroups", + ], + { + encoding: "utf-8", + stdio: "inherit", + } + ); - const repoRoot: string = path.resolve(__dirname, '..', '..'); - await runTests({ - vscodeExecutablePath, - extensionDevelopmentPath: repoRoot, - launchArgs: [ - path.resolve(repoRoot, 'test', 'test.code-workspace'), - '--disable-workspace-trust' - ], - extensionTestsPath: path.resolve(repoRoot, 'dist', 'test', 'index'), - extensionTestsEnv: { - DEBUGTELEMETRY: 'v' - } - }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } + const repoRoot: string = path.resolve(__dirname, "..", ".."); + await runTests({ + vscodeExecutablePath, + extensionDevelopmentPath: repoRoot, + launchArgs: [ + path.resolve(repoRoot, "test", "test.code-workspace"), + "--disable-workspace-trust", + ], + extensionTestsPath: path.resolve(repoRoot, "dist", "test", "index"), + extensionTestsEnv: { + DEBUGTELEMETRY: "v", + }, + }); + } catch (err) { + console.error("Failed to run tests"); + process.exit(1); + } } void main(); diff --git a/test/runWithSetting.ts b/test/runWithSetting.ts index 7c095ace6..533627292 100644 --- a/test/runWithSetting.ts +++ b/test/runWithSetting.ts @@ -3,22 +3,42 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ext, getGlobalSetting, updateGlobalSetting } from "../extension.bundle"; +import { + ext, + getGlobalSetting, + updateGlobalSetting, +} from "../extension.bundle"; -export async function runWithDatabasesSetting(key: string, value: string | boolean | undefined, callback: () => Promise): Promise { - await runWithSettingInternal(key, value, ext.prefix, callback); +export async function runWithDatabasesSetting( + key: string, + value: string | boolean | undefined, + callback: () => Promise +): Promise { + await runWithSettingInternal(key, value, ext.prefix, callback); } -export async function runWithSetting(key: string, value: string | boolean | undefined, callback: () => Promise): Promise { - await runWithSettingInternal(key, value, '', callback); +export async function runWithSetting( + key: string, + value: string | boolean | undefined, + callback: () => Promise +): Promise { + await runWithSettingInternal(key, value, "", callback); } -async function runWithSettingInternal(key: string, value: string | boolean | undefined, prefix: string, callback: () => Promise): Promise { - const oldValue: string | boolean | undefined = getGlobalSetting(key, prefix); - try { - await updateGlobalSetting(key, value, prefix); - await callback(); - } finally { - await updateGlobalSetting(key, oldValue, prefix); - } +async function runWithSettingInternal( + key: string, + value: string | boolean | undefined, + prefix: string, + callback: () => Promise +): Promise { + const oldValue: string | boolean | undefined = getGlobalSetting( + key, + prefix + ); + try { + await updateGlobalSetting(key, value, prefix); + await callback(); + } finally { + await updateGlobalSetting(key, oldValue, prefix); + } } diff --git a/test/test.code-workspace b/test/test.code-workspace index d1d77c70e..517ec9613 100644 --- a/test/test.code-workspace +++ b/test/test.code-workspace @@ -1,8 +1,8 @@ { - "folders": [ - { - "path": "../testWorkspace" - } - ], - "settings": {} + "folders": [ + { + "path": "../testWorkspace" + } + ], + "settings": {} } diff --git a/test/timeout.test.ts b/test/timeout.test.ts index f155a5cb4..b5567d5d2 100644 --- a/test/timeout.test.ts +++ b/test/timeout.test.ts @@ -3,118 +3,126 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { rejectOnTimeout, valueOnTimeout } from '../extension.bundle'; +import * as assert from "assert"; +import { rejectOnTimeout, valueOnTimeout } from "../extension.bundle"; suite("timeout Tests", () => { - suite("rejectOnTimeout", () => { - - test("executes synchronously", async () => { - let executed: boolean = false; - - await rejectOnTimeout(1, () => { - executed = true; - }); - - assert.equal(executed, true); - }); - - test("executes synchronously in promise", async () => { - let executed = false; - - await rejectOnTimeout(1, () => { - return new Promise((resolve, _reject) => { - executed = true; - resolve(); - }); - }); - - assert.equal(executed, true); - }); - - test("executes asynchnously before time-out", async () => { - let executed = false; - - await rejectOnTimeout(1000, () => { - return new Promise((resolve, _reject) => { - setTimeout(() => { executed = true; resolve(); }, 1); - }); - }); - assert.equal(executed, true); - }); - - test("timed out", async () => { - let executed = false; - - try { - await rejectOnTimeout(1, async () => { - await new Promise((resolve, _reject) => { - setTimeout(() => { executed = true; resolve(); }, 1000); - }); - }); - - assert.fail(null, null, "Expected exception"); - } catch (error) { - } - - assert.equal(executed, false); - }); - - test("throws before time-out", async () => { - const executed = false; - let error: Error = new Error("I haven't thrown up yet"); - - try { - await rejectOnTimeout(1000, async () => { - await new Promise((_resolve, _reject) => { - throw new Error("I threw up"); - }); - }); - } catch (err) { - error = err; - } - - assert.equal(executed, false); - assert.equal(error.message, "I threw up"); - }); - }); - - suite("valueOnTimeout", () => { - - test("executed", async () => { - const value = await valueOnTimeout(1000, 123, async () => { - return await new Promise((resolve, _reject) => { - setTimeout(() => { resolve(-123); }, 1); - }); - }); - - assert.equal(value, -123); - }); - - test("timed out", async () => { - const value = await valueOnTimeout(1, 123, async () => { - return await new Promise((resolve, _reject) => { - setTimeout(() => { resolve(-123); }, 1000); - }); - }); - - assert.equal(value, 123); - }); - - test("reject", async () => { - let error; - try { - await valueOnTimeout(1000, 123, async () => { - return await new Promise((_resolve, reject) => { - setTimeout(() => { reject(new Error("rejected")); }, 1); - }); - }); - } catch (err) { - error = err; - } - - assert.equal(error && error.message, "rejected"); - }); - }); - + suite("rejectOnTimeout", () => { + test("executes synchronously", async () => { + let executed: boolean = false; + + await rejectOnTimeout(1, () => { + executed = true; + }); + + assert.equal(executed, true); + }); + + test("executes synchronously in promise", async () => { + let executed = false; + + await rejectOnTimeout(1, () => { + return new Promise((resolve, _reject) => { + executed = true; + resolve(); + }); + }); + + assert.equal(executed, true); + }); + + test("executes asynchnously before time-out", async () => { + let executed = false; + + await rejectOnTimeout(1000, () => { + return new Promise((resolve, _reject) => { + setTimeout(() => { + executed = true; + resolve(); + }, 1); + }); + }); + assert.equal(executed, true); + }); + + test("timed out", async () => { + let executed = false; + + try { + await rejectOnTimeout(1, async () => { + await new Promise((resolve, _reject) => { + setTimeout(() => { + executed = true; + resolve(); + }, 1000); + }); + }); + + assert.fail(null, null, "Expected exception"); + } catch (error) {} + + assert.equal(executed, false); + }); + + test("throws before time-out", async () => { + const executed = false; + let error: Error = new Error("I haven't thrown up yet"); + + try { + await rejectOnTimeout(1000, async () => { + await new Promise((_resolve, _reject) => { + throw new Error("I threw up"); + }); + }); + } catch (err) { + error = err; + } + + assert.equal(executed, false); + assert.equal(error.message, "I threw up"); + }); + }); + + suite("valueOnTimeout", () => { + test("executed", async () => { + const value = await valueOnTimeout(1000, 123, async () => { + return await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve(-123); + }, 1); + }); + }); + + assert.equal(value, -123); + }); + + test("timed out", async () => { + const value = await valueOnTimeout(1, 123, async () => { + return await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve(-123); + }, 1000); + }); + }); + + assert.equal(value, 123); + }); + + test("reject", async () => { + let error; + try { + await valueOnTimeout(1000, 123, async () => { + return await new Promise((_resolve, reject) => { + setTimeout(() => { + reject(new Error("rejected")); + }, 1); + }); + }); + } catch (err) { + error = err; + } + + assert.equal(error && error.message, "rejected"); + }); + }); }); diff --git a/test/unit/DocDBUtils.test.ts b/test/unit/DocDBUtils.test.ts index 0fafd95cf..f88e82cbd 100644 --- a/test/unit/DocDBUtils.test.ts +++ b/test/unit/DocDBUtils.test.ts @@ -3,14 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { describe, it } from 'mocha'; +import * as assert from "assert"; +import { describe, it } from "mocha"; import { sanitizeId } from "../../src/docdb/tree/DocDBUtils"; describe("DocDBUtils", function () { - it("Replaces + with whitespace", function () { - const id = "a+b+c"; - const sanitizedId = sanitizeId(id); - assert.strictEqual(sanitizedId, "a b c"); - }); + it("Replaces + with whitespace", function () { + const id = "a+b+c"; + const sanitizedId = sanitizeId(id); + assert.strictEqual(sanitizedId, "a b c"); + }); }); diff --git a/test/unit/getClientConfig.test.ts b/test/unit/getClientConfig.test.ts index 33f8883e1..41bf2032a 100644 --- a/test/unit/getClientConfig.test.ts +++ b/test/unit/getClientConfig.test.ts @@ -3,180 +3,208 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { describe, it } from 'mocha'; -import { postgresDefaultPort } from '../../src/constants'; -import { PostgresServerType } from '../../src/postgres/abstract/models'; -import { getClientConfigs } from '../../src/postgres/getClientConfig'; -import { ParsedPostgresConnectionString } from '../../src/postgres/postgresConnectionStrings'; +import * as assert from "assert"; +import { describe, it } from "mocha"; +import { postgresDefaultPort } from "../../src/constants"; +import { PostgresServerType } from "../../src/postgres/abstract/models"; +import { getClientConfigs } from "../../src/postgres/getClientConfig"; +import { ParsedPostgresConnectionString } from "../../src/postgres/postgresConnectionStrings"; describe("getClientConfig Tests", () => { - describe("in subscription", () => { - it("Password only", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - user: "fake_user", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - // Cannot test null/undefined host because if it is the case, the code has thrown much earlier when constructing the ParsedPostgresConnectionString object. - - it("Password only - Missing port", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - user: "fake_user", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - assert(clientConfigs.password?.port === parseInt(postgresDefaultPort), "Should fallback to default port"); - }); - - it("Password only - missing username", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("No credential", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - user: "fake_user", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad only - Flexible server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Flexible, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd !== undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad and password - Flexible server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database", - user: "fake_user", - password: "fake_password", - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Flexible, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd !== undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad only - Single server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Single, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - }); - - describe("in attachment", () => { - it("Connection string only", async () => { - const rawConnectionString = "postgres://fake_connection_string"; - const parsedConnectionString = new ParsedPostgresConnectionString( - rawConnectionString, - { - host: "fake_host", - database: null - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, false, databaseName); - assert(clientConfigs.connectionString !== undefined); - }); - }); + describe("in subscription", () => { + it("Password only", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + port: "1234", + user: "fake_user", + password: "fake_password", + database: "fake_database", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + true, + databaseName + ); + assert(clientConfigs.password !== undefined); + assert(clientConfigs.azureAd === undefined); + assert(clientConfigs.connectionString === undefined); + }); + + // Cannot test null/undefined host because if it is the case, the code has thrown much earlier when constructing the ParsedPostgresConnectionString object. + + it("Password only - Missing port", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + user: "fake_user", + password: "fake_password", + database: "fake_database", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + true, + databaseName + ); + assert(clientConfigs.password !== undefined); + assert(clientConfigs.azureAd === undefined); + assert(clientConfigs.connectionString === undefined); + assert( + clientConfigs.password?.port === parseInt(postgresDefaultPort), + "Should fallback to default port" + ); + }); + + it("Password only - missing username", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + port: "1234", + password: "fake_password", + database: "fake_database", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + true, + databaseName + ); + assert(clientConfigs.password === undefined); + assert(clientConfigs.azureAd === undefined); + assert(clientConfigs.connectionString === undefined); + }); + + it("No credential", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + port: "1234", + user: "fake_user", + database: "fake_database", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + true, + databaseName + ); + assert(clientConfigs.password === undefined); + assert(clientConfigs.azureAd === undefined); + assert(clientConfigs.connectionString === undefined); + }); + + it("Aad only - Flexible server", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + port: "1234", + database: "fake_database", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + true, + databaseName, + "fake_azureAd_userId", + async () => "fake_token" + ); + assert(clientConfigs.password === undefined); + assert(clientConfigs.azureAd !== undefined); + assert(clientConfigs.connectionString === undefined); + }); + + it("Aad and password - Flexible server", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + port: "1234", + database: "fake_database", + user: "fake_user", + password: "fake_password", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + true, + databaseName, + "fake_azureAd_userId", + async () => "fake_token" + ); + assert(clientConfigs.password !== undefined); + assert(clientConfigs.azureAd !== undefined); + assert(clientConfigs.connectionString === undefined); + }); + + it("Aad only - Single server", async () => { + const parsedConnectionString = new ParsedPostgresConnectionString( + "", + { + host: "fake_host.com", + port: "1234", + database: "fake_database", + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Single, + true, + databaseName, + "fake_azureAd_userId", + async () => "fake_token" + ); + assert(clientConfigs.password === undefined); + assert(clientConfigs.azureAd === undefined); + assert(clientConfigs.connectionString === undefined); + }); + }); + + describe("in attachment", () => { + it("Connection string only", async () => { + const rawConnectionString = "postgres://fake_connection_string"; + const parsedConnectionString = new ParsedPostgresConnectionString( + rawConnectionString, + { + host: "fake_host", + database: null, + } + ); + const databaseName = "fake_database_2"; + + const clientConfigs = await getClientConfigs( + parsedConnectionString, + PostgresServerType.Flexible, + false, + databaseName + ); + assert(clientConfigs.connectionString !== undefined); + }); + }); }); diff --git a/test/util/getIp.test.ts b/test/util/getIp.test.ts index 3e2b0cbc1..4fe42e7a5 100644 --- a/test/util/getIp.test.ts +++ b/test/util/getIp.test.ts @@ -3,43 +3,53 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createTestActionContext } from '@microsoft/vscode-azext-dev'; -import * as assert from 'assert'; -import { isIPv4 } from 'net'; -import { getPublicIpv4, isIpInRanges } from '../../extension.bundle'; +import { createTestActionContext } from "@microsoft/vscode-azext-dev"; +import * as assert from "assert"; +import { isIPv4 } from "net"; +import { getPublicIpv4, isIpInRanges } from "../../extension.bundle"; suite("getPublicIpv4", () => { - test("get IP", async () => { - try { - const context = await createTestActionContext(); - const ip = await getPublicIpv4(context); - assert(isIPv4(ip), "IP address isn't v4"); - } catch (error) { - assert(false, error.message ?? "Fail to get IP address"); - } - }); + test("get IP", async () => { + try { + const context = await createTestActionContext(); + const ip = await getPublicIpv4(context); + assert(isIPv4(ip), "IP address isn't v4"); + } catch (error) { + assert(false, error.message ?? "Fail to get IP address"); + } + }); }); suite("isIpInRanges", function () { - const ip = "12.34.56.78"; - test("Includes ip at start", function () { - const ranges = [{ startIpAddress: "12.34.56.78", endIpAddress: "12.34.56.80" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Includes ip at end", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.78" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Includes ip in range", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.80" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Excludes ip before start", function () { - const ranges = [{ startIpAddress: "12.34.56.80", endIpAddress: "12.34.56.80" }]; - assert(!isIpInRanges(ip, ranges)); - }); - test("Excludes ip after end", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.76" }]; - assert(!isIpInRanges(ip, ranges)); - }); + const ip = "12.34.56.78"; + test("Includes ip at start", function () { + const ranges = [ + { startIpAddress: "12.34.56.78", endIpAddress: "12.34.56.80" }, + ]; + assert(isIpInRanges(ip, ranges)); + }); + test("Includes ip at end", function () { + const ranges = [ + { startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.78" }, + ]; + assert(isIpInRanges(ip, ranges)); + }); + test("Includes ip in range", function () { + const ranges = [ + { startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.80" }, + ]; + assert(isIpInRanges(ip, ranges)); + }); + test("Excludes ip before start", function () { + const ranges = [ + { startIpAddress: "12.34.56.80", endIpAddress: "12.34.56.80" }, + ]; + assert(!isIpInRanges(ip, ranges)); + }); + test("Excludes ip after end", function () { + const ranges = [ + { startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.76" }, + ]; + assert(!isIpInRanges(ip, ranges)); + }); }); diff --git a/test/util/setEnvironmentVariables.test.ts b/test/util/setEnvironmentVariables.test.ts index 333a6803b..ad8e937b1 100644 --- a/test/util/setEnvironmentVariables.test.ts +++ b/test/util/setEnvironmentVariables.test.ts @@ -3,34 +3,34 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { isWindows } from '../../extension.bundle'; -import { setEnvironmentVariables } from './setEnvironmentVariables'; +import * as assert from "assert"; +import { isWindows } from "../../extension.bundle"; +import { setEnvironmentVariables } from "./setEnvironmentVariables"; suite("setEnvironmentVariables (test util)", () => { - test("restore", () => { - const currentPath = process.env.PATH; - const dispose = setEnvironmentVariables({ PATH: "new path" }); + test("restore", () => { + const currentPath = process.env.PATH; + const dispose = setEnvironmentVariables({ PATH: "new path" }); - assert.equal(process.env.PATH, 'new path'); + assert.equal(process.env.PATH, "new path"); - dispose.dispose(); + dispose.dispose(); - assert.equal(process.env.PATH, currentPath); - }); + assert.equal(process.env.PATH, currentPath); + }); - test("different casings (Windows)", () => { - if (isWindows) { - const currentPath = process.env.paTH; - const dispose = setEnvironmentVariables({ PAth: "new path" }); + test("different casings (Windows)", () => { + if (isWindows) { + const currentPath = process.env.paTH; + const dispose = setEnvironmentVariables({ PAth: "new path" }); - assert.equal(process.env.path, 'new path'); - assert.equal(process.env.PATH, 'new path'); + assert.equal(process.env.path, "new path"); + assert.equal(process.env.PATH, "new path"); - dispose.dispose(); + dispose.dispose(); - assert.equal(process.env.path, currentPath); - assert.equal(process.env.PATH, currentPath); - } - }); + assert.equal(process.env.path, currentPath); + assert.equal(process.env.PATH, currentPath); + } + }); }); diff --git a/test/util/setEnvironmentVariables.ts b/test/util/setEnvironmentVariables.ts index 7dc468729..5d210ea94 100644 --- a/test/util/setEnvironmentVariables.ts +++ b/test/util/setEnvironmentVariables.ts @@ -8,28 +8,33 @@ import { IDisposable } from "../../extension.bundle"; /** * Add a set of environment variables, and return to the previous values after disposing the result */ -export function setEnvironmentVariables(env: { [key: string]: string }): IDisposable { - const setRestoreEnv = new SetRestoreEnv(); - setRestoreEnv.set(env); - return setRestoreEnv; +export function setEnvironmentVariables(env: { + [key: string]: string; +}): IDisposable { + const setRestoreEnv = new SetRestoreEnv(); + setRestoreEnv.set(env); + return setRestoreEnv; } class SetRestoreEnv implements IDisposable { - private _previousValues: { [key: string]: string } = {}; + private _previousValues: { [key: string]: string } = {}; - public set(env: { [key: string]: string }): void { - for (const key of Object.keys(env || {})) { - [this._previousValues[key], process.env[key]] = [process.env[key]!, env[key]]; - } - } + public set(env: { [key: string]: string }): void { + for (const key of Object.keys(env || {})) { + [this._previousValues[key], process.env[key]] = [ + process.env[key]!, + env[key], + ]; + } + } - public restore(): void { - for (const key of Object.keys(this._previousValues)) { - process.env[key] = this._previousValues[key]; - } - } + public restore(): void { + for (const key of Object.keys(this._previousValues)) { + process.env[key] = this._previousValues[key]; + } + } - public dispose(): void { - this.restore(); - } + public dispose(): void { + this.restore(); + } } diff --git a/test/wrapError.test.ts b/test/wrapError.test.ts index 3663aa7ee..189ca5a8b 100644 --- a/test/wrapError.test.ts +++ b/test/wrapError.test.ts @@ -3,51 +3,66 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import * as os from 'os'; -import { wrapError } from '../extension.bundle'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as assert from "assert"; +import * as os from "os"; +import { wrapError } from "../extension.bundle"; suite("wrapError", () => { - test("just outer string", () => { - const wrapped = wrapError('Outer error'); - assert(typeof wrapped === 'string'); - assert.equal(wrapped, 'Outer error'); - }); - - test("just outer error", () => { - const wrapped = wrapError(new Error('Outer error')); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, 'Outer error'); - }); - - test("just inner", () => { - const wrapped = wrapError(undefined, 'Inner error'); - assert(typeof wrapped === 'string'); - assert.equal(wrapped, 'Inner error'); - }); - - test("outer string, inner string", () => { - const wrapped = wrapError('Outer error.', 'Inner error.'); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer error, inner string", () => { - const wrapped = wrapError(new Error('Outer error.'), 'Inner error.'); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer error, inner error", () => { - const wrapped = wrapError(new Error('Outer error.'), new Error('Inner error.')); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer string, inner error", () => { - const wrapped = wrapError('Outer error.', new Error('Inner error.')); - assert(wrapped instanceof Error); - assert(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); + test("just outer string", () => { + const wrapped = wrapError("Outer error"); + assert(typeof wrapped === "string"); + assert.equal(wrapped, "Outer error"); + }); + + test("just outer error", () => { + const wrapped = wrapError(new Error("Outer error")); + assert(wrapped instanceof Error); + assert.equal(parseError(wrapped).message, "Outer error"); + }); + + test("just inner", () => { + const wrapped = wrapError(undefined, "Inner error"); + assert(typeof wrapped === "string"); + assert.equal(wrapped, "Inner error"); + }); + + test("outer string, inner string", () => { + const wrapped = wrapError("Outer error.", "Inner error."); + assert(wrapped instanceof Error); + assert.equal( + parseError(wrapped).message, + `Outer error.${os.EOL}Inner error.` + ); + }); + + test("outer error, inner string", () => { + const wrapped = wrapError(new Error("Outer error."), "Inner error."); + assert(wrapped instanceof Error); + assert.equal( + parseError(wrapped).message, + `Outer error.${os.EOL}Inner error.` + ); + }); + + test("outer error, inner error", () => { + const wrapped = wrapError( + new Error("Outer error."), + new Error("Inner error.") + ); + assert(wrapped instanceof Error); + assert.equal( + parseError(wrapped).message, + `Outer error.${os.EOL}Inner error.` + ); + }); + + test("outer string, inner error", () => { + const wrapped = wrapError("Outer error.", new Error("Inner error.")); + assert(wrapped instanceof Error); + assert( + parseError(wrapped).message, + `Outer error.${os.EOL}Inner error.` + ); + }); }); diff --git a/tsconfig.json b/tsconfig.json index 70851034c..2a36e70e3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,33 +1,23 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6", - "dom" - ], - "sourceMap": true, - "noImplicitThis": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "strictNullChecks": true, - "skipLibCheck": true, - "noUnusedParameters": true, - "rootDir": ".", - "experimentalDecorators": true, - "baseUrl": "./", - "alwaysStrict": true, - "paths": { - "*": [ - "node_modules/@types/*", - "*" - ] - } - }, - "exclude": [ - "node_modules", - ".vscode-test", - "gulpfile.ts" - ] + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": ["es6", "dom"], + "sourceMap": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "strictNullChecks": true, + "skipLibCheck": true, + "noUnusedParameters": true, + "rootDir": ".", + "experimentalDecorators": true, + "baseUrl": "./", + "alwaysStrict": true, + "paths": { + "*": ["node_modules/@types/*", "*"] + } + }, + "exclude": ["node_modules", ".vscode-test", "gulpfile.ts"] } diff --git a/webpack.config.js b/webpack.config.js index 70a3c0468..e4e40a706 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,55 +7,51 @@ // See https://github.com/Microsoft/vscode-azuretools/wiki/webpack for guidance -'use strict'; +"use strict"; -const process = require('process'); -const webpack = require('webpack'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); +const process = require("process"); +const webpack = require("webpack"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); const dev = require("@microsoft/vscode-azext-dev"); let DEBUG_WEBPACK = !!process.env.DEBUG_WEBPACK; let config = dev.getDefaultWebpackConfig({ - projectRoot: __dirname, - verbosity: DEBUG_WEBPACK ? 'debug' : 'normal', - - externalNodeModules: [ - // Modules that we can't easily webpack for some reason. - // These and their dependencies will be copied into node_modules rather than placed in the bundle - // Keep this list small, because all the subdependencies will also be excluded - 'mongodb', - 'pg', - 'pg-structure' - ], - entries: { - // Note: Each entry is a completely separate Node.js application that cannot interact with any - // of the others, and that individually includes all dependencies necessary (i.e. common - // dependencies will have a copy in each entry file, no sharing). - - // Create a separate module bundle for the mongo language server (doesn't share any code with extension.bundle.js) - './mongo-languageServer.bundle': './src/mongo/languageServer.ts' - }, - - externals: { - }, // end of externals - - loaderRules: [ - ], // end of loaderRules - - - plugins: [ - // Replace vscode-languageserver/lib/files.js with a modified version that doesn't have webpack issues - new webpack.NormalModuleReplacementPlugin( - - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/vscode-languageserver-files-stub.js') - ) - ] + projectRoot: __dirname, + verbosity: DEBUG_WEBPACK ? "debug" : "normal", + + externalNodeModules: [ + // Modules that we can't easily webpack for some reason. + // These and their dependencies will be copied into node_modules rather than placed in the bundle + // Keep this list small, because all the subdependencies will also be excluded + "mongodb", + "pg", + "pg-structure", + ], + entries: { + // Note: Each entry is a completely separate Node.js application that cannot interact with any + // of the others, and that individually includes all dependencies necessary (i.e. common + // dependencies will have a copy in each entry file, no sharing). + + // Create a separate module bundle for the mongo language server (doesn't share any code with extension.bundle.js) + "./mongo-languageServer.bundle": "./src/mongo/languageServer.ts", + }, + + externals: {}, // end of externals + + loaderRules: [], // end of loaderRules + + plugins: [ + // Replace vscode-languageserver/lib/files.js with a modified version that doesn't have webpack issues + new webpack.NormalModuleReplacementPlugin( + /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, + require.resolve("./build/vscode-languageserver-files-stub.js") + ), + ], }); if (DEBUG_WEBPACK) { - console.log('Config:', config); + console.log("Config:", config); } module.exports = config; From 4a277ed1b2debe3d991050f20754ab8dd7082d7e Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Thu, 9 Nov 2023 15:06:43 +0200 Subject: [PATCH 09/33] squash! --- .github/CODEOWNERS | 1 - .github/workflows/bump-version-pr.yaml | 30 ----------------- .github/workflows/feature-request.yml | 43 ------------------------ .github/workflows/info-needed-closer.yml | 27 --------------- .github/workflows/locker.yml | 24 ------------- 5 files changed, 125 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/bump-version-pr.yaml delete mode 100644 .github/workflows/feature-request.yml delete mode 100644 .github/workflows/info-needed-closer.yml delete mode 100644 .github/workflows/locker.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index f426a03c5..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @Microsoft/vscodeazuretoolsdev diff --git a/.github/workflows/bump-version-pr.yaml b/.github/workflows/bump-version-pr.yaml deleted file mode 100644 index dec36e0a9..000000000 --- a/.github/workflows/bump-version-pr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Bump version after release - -# Run when release is published, or manually triggered -on: - release: - types: [published] - workflow_dispatch: - -jobs: - bump: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Bump version - id: bump - uses: alexweininger/bump-prerelease-version@v0.1.1 - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - title: ${{ env.MESSAGE }} - body: Automatically created by ${{ env.RUN_LINK }} - commit-message: ${{ env.MESSAGE }} - branch: bot/bump-${{ steps.bump.outputs.new-version }} - base: main - author: GitHub - env: - RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - MESSAGE: Bump version after release diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml deleted file mode 100644 index 94c0c5144..000000000 --- a/.github/workflows/feature-request.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Feature Request Manager -on: - issues: - types: [milestoned] - schedule: - - cron: 15 5 * * * # 10:15pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: actions/checkout@v3 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - run: npm install --production --prefix ./actions - - name: Run Feature Request Manager - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: ./actions/feature-request - with: - token: ${{secrets.AZCODE_BOT_PAT}} - candidateMilestoneID: 28 - candidateMilestoneName: "Backlog Candidates" - backlogMilestoneID: 33 - featureRequestLabel: "feature" - upvotesRequired: 5 - numCommentsOverride: 10 - initComment: "This feature request is now a candidate for our backlog. The community has 240 days to upvote the issue. If it receives 5 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectComment: ":slightly_frowning_face: In the last 60 days, this issue has received less than 5 community upvotes and we closed it. Still a big Thank You to you for taking the time to create it! To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectLabel: "out of scope" - warnComment: "This issue has become stale and is at risk of being closed. The community has 60 days to upvote the issue. If it receives 5 upvotes we will keep it open and take another look. If not, we will close it. To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - labelsToExclude: "P0,P1" - acceptComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - warnDays: 60 - closeDays: 240 - milestoneDelaySeconds: 60 - diff --git a/.github/workflows/info-needed-closer.yml b/.github/workflows/info-needed-closer.yml deleted file mode 100644 index 9304007a4..000000000 --- a/.github/workflows/info-needed-closer.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Info Needed Closer -on: - schedule: - - cron: 30 5 * * * # 10:30pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Info Needed Closer - uses: ./actions/needs-more-info-closer - with: - token: ${{secrets.AZCODE_BOT_PAT}} - label: info-needed - closeDays: 14 - closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/azcodeissuereporting) guidelines.\n\nHappy Coding!" - pingDays: 80 - pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information." diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml deleted file mode 100644 index 050406703..000000000 --- a/.github/workflows/locker.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Locker -on: - schedule: - - cron: 0 5 * * * # 10:00pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Locker - uses: ./actions/locker - with: - token: ${{secrets.AZCODE_BOT_PAT}} - daysSinceClose: 45 - daysSinceUpdate: 7 From 003c70fb98c06a15b68c47e58d30cdfb32f1ec76 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Thu, 9 Nov 2023 19:43:28 +0200 Subject: [PATCH 10/33] squash! --- package-lock.json | 21347 -------------------------------------------- package.json | 108 +- 2 files changed, 54 insertions(+), 21401 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e16bd2f53..000000000 --- a/package-lock.json +++ /dev/null @@ -1,21347 +0,0 @@ -{ - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "license": "SEE LICENSE IN LICENSE.md", - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "engines": { - "vscode": "^1.66.0" - } - }, - "node_modules/@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@azure/abort-controller/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "node_modules/@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-cosmosdb/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-subscriptions/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-auth/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-client/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-lro/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "dependencies": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-paging/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-tracing/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-util/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/cosmos/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/cosmos/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/logger/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "node_modules/@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - } - }, - "node_modules/@azure/ms-rest-js/node_modules/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, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "dependencies": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "dependencies": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - }, - "peerDependencies": { - "tslib": "*" - } - }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "node_modules/@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "dependencies": { - "@typescript-eslint/parser": "^4.28.5" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=4", - "eslint": ">=7", - "eslint-plugin-import": ">=2" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "dependencies": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "dependencies": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "bin": { - "vscode-sort-package-json": "scripts/sortPackageJson.mjs" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "dependencies": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - }, - "node_modules/@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "dependencies": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "node_modules/@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "dependencies": { - "@types/webpack": "*" - } - }, - "node_modules/@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "node_modules/@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "dependencies": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "node_modules/@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "dependencies": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - } - }, - "node_modules/@types/gulp/node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/gulp/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@types/gulp/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@types/gulp/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/gulp/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/@types/gulp/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/@types/gulp/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "node_modules/@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "dependencies": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "node_modules/@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "node_modules/@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "node_modules/@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/uglify-js/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "node_modules/@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "node_modules/@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "dependencies": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "node_modules/@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "node_modules/@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "dependencies": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/webpack/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "dependencies": { - "fast-memoize": "^2.3.2" - } - }, - "node_modules/@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "dependencies": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - }, - "engines": { - "vscode": "^1.60.0" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/@vscode/test-electron/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "engines": { - "node": ">= 0.6.15" - } - }, - "node_modules/adal-node/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "node_modules/antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true, - "bin": { - "antlr4ts": "antlr4ts" - } - }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "dependencies": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - }, - "engines": { - "node": ">=8.9.0" - }, - "peerDependencies": { - "webpack": "*" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "node_modules/copy-props/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "dependencies": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/copy-webpack-plugin/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/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, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true, - "engines": { - "node": ">0.4.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "dev": true - }, - "node_modules/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 - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/enquirer/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/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 - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-glob/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli/node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, - "engines": { - "node": ">=10.23.2" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "dependencies": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/indexable-array/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/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 - }, - "node_modules/log-symbols/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true, - "engines": { - "node": ">= 6.14.4" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "peerDependencies": { - "mocha": ">=2.2.5" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-junit-reporter/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha-junit-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - } - }, - "node_modules/mocha-multi-reporters/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/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 - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - }, - "peerDependenciesMeta": { - "aws4": { - "optional": true - }, - "bson-ext": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "mongodb-extjson": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "dependencies": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/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, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "dependencies": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dependencies": { - "split": "^1.0.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "dependencies": { - "parseley": "^0.7.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/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 - }, - "node_modules/slice-ansi/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-color/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/table/node_modules/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/tas-client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tmp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "dependencies": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "engines": { - "node": ">=6.11.5" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/ts-loader/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "out/vsce" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "dependencies": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - } - }, - "node_modules/vscode-json-languageservice/node_modules/vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "dependencies": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "engines": { - "vscode": "^1.41.0" - } - }, - "node_modules/vscode-languageclient/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "dependencies": { - "vscode-languageserver-protocol": "^3.15.3" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "dependencies": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "node_modules/vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "dependencies": { - "tas-client": "0.1.45" - }, - "engines": { - "vscode": "^1.19.1" - } - }, - "node_modules/vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-cli/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/webpack-cli/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, - "node_modules/yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "requires": { - "tslib": "^2.0.0" - }, - "dependencies": { - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - } - } - }, - "@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==" - }, - "@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "requires": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - }, - "dependencies": { - "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 - } - } - }, - "@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "requires": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "requires": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "requires": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^4.28.5" - } - }, - "@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "requires": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "dependencies": { - "@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "requires": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "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 - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - } - }, - "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } - } - } - }, - "@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "requires": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - } - } - }, - "@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "requires": {} - }, - "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - } - }, - "@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "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" - } - } - } - }, - "@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "requires": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, - "@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "requires": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - }, - "dependencies": { - "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" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "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" - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.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" - } - }, - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "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" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true - } - } - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "requires": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "requires": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - } - }, - "@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - } - }, - "@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "requires": { - "fast-memoize": "^2.3.2" - } - }, - "@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "requires": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - } - }, - "@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "dependencies": { - "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" - } - } - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "requires": {} - }, - "@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "requires": {} - }, - "adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - } - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "requires": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - } - } - }, - "copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "requires": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "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" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.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" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true - }, - "dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "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 - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "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==" - }, - "eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "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" - } - }, - "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" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "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 - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.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" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.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" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "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" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "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" - } - } - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "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" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "requires": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.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": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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" - } - } - } - }, - "loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "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.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^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" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.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 - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "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" - } - }, - "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 - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "requires": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "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 - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "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" - } - } - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "requires": { - "require-at": "^1.0.6" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "requires": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "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 - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "requires": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - } - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "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" - }, - "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" - } - }, - "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 - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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 - } - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "requires": { - "parseley": "^0.7.0" - } - }, - "semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=" - }, - "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "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 - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.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" - } - }, - "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 - }, - "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 - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "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" - } - } - } - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "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 - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "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" - } - } - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } - } - }, - "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - } - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "requires": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - }, - "dependencies": { - "vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - } - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "requires": { - "vscode-languageserver-protocol": "^3.15.3" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "requires": { - "tas-client": "0.1.45" - } - }, - "vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - } - } - }, - "webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - } - } - }, - "webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - } - }, - "webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "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" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index b710e8ca1..8da3d9806 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "displayName": "Azure Databases", "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", "engines": { - "vscode": "^1.66.0" + "vscode": "1.66.0" }, "galleryBanner": { "color": "#3c3c3c", @@ -1052,61 +1052,61 @@ "prepare": "husky install" }, "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.1", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.12", + "@types/fs-extra": "11.0.4", + "@types/gulp": "4.0.17", + "@types/mocha": "10.0.4", + "@types/mongodb": "4.0.6", + "@types/node": "20.9.0", + "@types/pg": "8.10.9", + "@types/vscode": "1.84.1", + "@typescript-eslint/eslint-plugin": "6.10.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.53.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2" }, "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.2.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" }, "extensionDependencies": [ "ms-vscode.azure-account", From 7b478baffe9ee5439a39f70a51ba2fbedb6ff2cf Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sat, 11 Nov 2023 14:43:43 +0200 Subject: [PATCH 11/33] squash! --- Source/AzureDBExperiences.ts | 250 +- Source/DatabasesFileSystem.ts | 147 +- Source/ParsedConnectionString.ts | 36 +- Source/azureAccountUtils.ts | 27 +- .../api/DatabaseAccountTreeItemInternal.ts | 220 +- .../commands/api/DatabaseTreeItemInternal.ts | 93 +- Source/commands/api/apiCache.ts | 82 +- Source/commands/api/findTreeItem.ts | 355 +- Source/commands/api/pickTreeItem.ts | 220 +- Source/commands/api/revealTreeItem.ts | 29 +- .../DatabaseAccountDeleteStep.ts | 14 +- .../IDeleteWizardContext.ts | 25 +- .../deleteCosmosDBAccount.ts | 69 +- .../deleteDatabaseAccount.ts | 60 +- Source/commands/importDocuments.ts | 328 +- Source/constants.ts | 133 +- Source/docdb/docDBConnectionStrings.ts | 78 +- Source/docdb/getCosmosClient.ts | 35 +- Source/docdb/registerDocDBCommands.ts | 238 +- Source/docdb/tree/DocDBAccountTreeItem.ts | 56 +- Source/docdb/tree/DocDBAccountTreeItemBase.ts | 188 +- Source/docdb/tree/DocDBCollectionTreeItem.ts | 187 +- Source/docdb/tree/DocDBDatabaseTreeItem.ts | 31 +- .../docdb/tree/DocDBDatabaseTreeItemBase.ts | 329 +- Source/docdb/tree/DocDBDocumentTreeItem.ts | 286 +- Source/docdb/tree/DocDBDocumentsTreeItem.ts | 269 +- .../tree/DocDBStoredProcedureTreeItem.ts | 134 +- .../tree/DocDBStoredProceduresTreeItem.ts | 216 +- Source/docdb/tree/DocDBTreeItemBase.ts | 79 +- Source/docdb/tree/DocDBUtils.ts | 2 +- Source/docdb/tree/IDocDBTreeRoot.ts | 9 +- Source/extension.ts | 592 ++-- Source/extensionVariables.ts | 61 +- Source/getExtensionApi.ts | 41 +- Source/graph/gremlinEndpoints.ts | 74 +- Source/graph/registerGraphCommands.ts | 125 +- Source/graph/tree/GraphAccountTreeItem.ts | 87 +- Source/graph/tree/GraphCollectionTreeItem.ts | 181 +- Source/graph/tree/GraphDatabaseTreeItem.ts | 109 +- Source/graph/tree/GraphTreeItem.ts | 105 +- Source/mongo/MongoCommand.ts | 26 +- Source/mongo/MongoScrapbook.ts | 1135 +++---- Source/mongo/MongoShell.ts | 353 +- Source/mongo/connectToMongoClient.ts | 87 +- Source/mongo/errorListeners.ts | 98 +- Source/mongo/grammar/mongoLexer.ts | 535 ++- Source/mongo/grammar/mongoListener.ts | 36 +- Source/mongo/grammar/mongoParser.ts | 2994 ++++++++--------- Source/mongo/grammar/mongoVisitor.ts | 32 +- Source/mongo/grammar/visitors.ts | 157 +- Source/mongo/languageClient.ts | 120 +- Source/mongo/languageServer.ts | 4 +- Source/mongo/mongoConnectionStrings.ts | 158 +- Source/mongo/registerMongoCommands.ts | 500 +-- Source/mongo/services/IConnectionParams.ts | 6 +- .../mongo/services/MongoCodeLensProvider.ts | 130 +- .../mongo/services/completionItemProvider.ts | 1015 +++--- Source/mongo/services/languageService.ts | 193 +- Source/mongo/services/mongoScript.ts | 195 +- Source/mongo/services/schemaService.ts | 1336 ++++---- Source/mongo/setConnectedNode.ts | 10 +- Source/mongo/tree/IMongoTreeRoot.ts | 3 +- Source/mongo/tree/MongoAccountTreeItem.ts | 307 +- Source/mongo/tree/MongoCollectionTreeItem.ts | 753 ++--- Source/mongo/tree/MongoDatabaseTreeItem.ts | 611 ++-- Source/mongo/tree/MongoDocumentTreeItem.ts | 182 +- .../abstract/AbstractPostgresClient.ts | 30 +- Source/postgres/abstract/models.ts | 73 +- .../postgres/commands/checkAuthentication.ts | 56 +- .../commands/configurePostgresFirewall.ts | 128 +- .../commands/connectPostgresDatabase.ts | 70 +- .../postgres/commands/copyConnectionString.ts | 76 +- .../commands/createPostgresDatabase.ts | 49 +- .../IPostgresQueryWizardContext.ts | 5 +- .../IPostgresFunctionQueryWizardContext.ts | 5 +- .../function/createPostgresFunctionQuery.ts | 22 +- .../function/steps/FunctionQueryCreateStep.ts | 24 +- .../FunctionQueryCustomReturnTypeStep.ts | 19 +- .../function/steps/FunctionQueryNameStep.ts | 25 +- .../steps/FunctionQueryReturnTypeStep.ts | 87 +- .../runPostgresQueryWizard.ts | 29 +- .../createPostgresStoredProcedureQuery.ts | 17 +- .../steps/StoredProcedureQueryCreateStep.ts | 20 +- .../steps/StoredProcedureQueryNameStep.ts | 23 +- .../createPostgresQuery/validateIdentifier.ts | 203 +- .../IPostgresServerWizardContext.ts | 34 +- .../steps/PostgresServerConfirmPWStep.ts | 40 +- .../steps/PostgresServerCreateStep.ts | 205 +- .../steps/PostgresServerCredPWStep.ts | 99 +- .../steps/PostgresServerCredUserStep.ts | 100 +- .../steps/PostgresServerNameStep.ts | 143 +- .../steps/PostgresServerSetCredentialsStep.ts | 84 +- .../steps/PostgresServerSkuStep.ts | 465 ++- .../commands/deletePostgresDatabase.ts | 61 +- .../commands/deletePostgresFunction.ts | 57 +- .../postgres/commands/deletePostgresServer.ts | 37 +- .../commands/deletePostgresStoredProcedure.ts | 60 +- .../postgres/commands/deletePostgresTable.ts | 56 +- .../commands/enterPostgresCredentials.ts | 153 +- .../executePostgresQueryInDocument.ts | 127 +- .../postgres/commands/openPostgresFunction.ts | 23 +- .../commands/openPostgresStoredProcedure.ts | 24 +- .../commands/registerPostgresCommands.ts | 166 +- .../commands/setPostgresCredentials.ts | 44 +- Source/postgres/getClientConfig.ts | 187 +- .../postgres/getPostgresProcedureQueryRows.ts | 61 +- Source/postgres/getTables.ts | 34 +- Source/postgres/postgresConnectionStrings.ts | 123 +- Source/postgres/postgresConstants.ts | 6 +- Source/postgres/runPostgresQuery.ts | 21 +- .../services/PostgresCodeLensProvider.ts | 122 +- Source/postgres/showPostgresQuery.ts | 16 +- Source/postgres/tree/ClientConfigFactory.ts | 171 +- .../postgres/tree/PostgresColumnTreeItem.ts | 41 +- .../postgres/tree/PostgresDatabaseTreeItem.ts | 252 +- .../postgres/tree/PostgresFunctionTreeItem.ts | 70 +- .../tree/PostgresFunctionsTreeItem.ts | 70 +- .../tree/PostgresResourcesTreeItemBase.ts | 26 +- .../postgres/tree/PostgresServerTreeItem.ts | 611 ++-- .../tree/PostgresStoredProcedureTreeItem.ts | 68 +- .../tree/PostgresStoredProceduresTreeItem.ts | 74 +- Source/postgres/tree/PostgresTableTreeItem.ts | 92 +- .../postgres/tree/PostgresTablesTreeItem.ts | 81 +- Source/resolver/AppResolver.ts | 149 +- Source/resolver/DatabaseWorkspaceProvider.ts | 48 +- .../ResolvedDatabaseAccountResource.ts | 117 +- .../resolver/ResolvedDocDBAccountResource.ts | 63 +- .../resolver/ResolvedMongoAccountResource.ts | 22 +- .../ResolvedPostgresServerResource.ts | 79 +- Source/table/tree/TableAccountTreeItem.ts | 50 +- Source/tree/AttachedAccountsTreeItem.ts | 973 +++--- .../tree/AzureAccountTreeItemWithAttached.ts | 65 +- Source/tree/AzureDBAPIStep.ts | 159 +- .../CosmosDBAccountCapacityStep.ts | 73 +- .../CosmosDBAccountCreateStep.ts | 130 +- .../CosmosDBAccountNameStep.ts | 85 +- .../ICosmosDBWizardContext.ts | 24 +- Source/tree/IAzureDBWizardContext.ts | 10 +- Source/tree/SubscriptionTreeItem.ts | 460 +-- Source/utils/InteractiveChildProcess.ts | 336 +- Source/utils/activityUtils.ts | 13 +- Source/utils/array.ts | 18 +- Source/utils/azureClients.ts | 39 +- Source/utils/azureUtils.ts | 12 +- Source/utils/cp.ts | 17 +- Source/utils/getIp.ts | 106 +- Source/utils/getSecretStorageKey.ts | 2 +- Source/utils/improveError.ts | 14 +- Source/utils/localize.ts | 2 +- Source/utils/nonNull.ts | 49 +- Source/utils/openUrl.ts | 8 +- Source/utils/randomUtils.ts | 17 +- Source/utils/settingUtils.ts | 98 +- Source/utils/timeout.ts | 70 +- Source/utils/vscodeUtils.ts | 180 +- Source/utils/workspacUtils.ts | 21 +- Source/utils/wrapError.ts | 26 +- Source/vscode-cosmosdb.api.d.ts | 154 +- Source/vscode-cosmosdbgraph.api.d.ts | 26 +- 159 files changed, 10396 insertions(+), 14960 deletions(-) diff --git a/Source/AzureDBExperiences.ts b/Source/AzureDBExperiences.ts index 97d2221cc..be9765dc6 100644 --- a/Source/AzureDBExperiences.ts +++ b/Source/AzureDBExperiences.ts @@ -3,202 +3,116 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "./utils/nonNull"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import { nonNullProp } from './utils/nonNull'; export enum API { - MongoDB = "MongoDB", - Graph = "Graph", - Table = "Table", - Core = "Core", - PostgresSingle = "PostgresSingle", - PostgresFlexible = "PostgresFlexible", + MongoDB = 'MongoDB', + Graph = 'Graph', + Table = 'Table', + Core = 'Core', + PostgresSingle = 'PostgresSingle', + PostgresFlexible = 'PostgresFlexible' } export enum DBAccountKind { - MongoDB = "MongoDB", - GlobalDocumentDB = "GlobalDocumentDB", + MongoDB = 'MongoDB', + GlobalDocumentDB = 'GlobalDocumentDB' } -export type CapabilityName = "EnableGremlin" | "EnableTable"; +export type CapabilityName = 'EnableGremlin' | 'EnableTable'; export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { - api: api, - shortName: api, - longName: api, - kind: DBAccountKind.GlobalDocumentDB, - tag: api, - }; - } - return info; + let info = experiencesMap.get(api); + if (!info) { + info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; + } + return info; } -export function getExperienceLabel( - databaseAccount: DatabaseAccountGetResults -): string { - const experience: Experience | undefined = - tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = ( - (databaseAccount && - databaseAccount.tags && - databaseAccount.tags.defaultExperience) - ); - const firstCapability = - databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ""); - return ( - defaultExperience || - firstCapabilityName || - nonNullProp(databaseAccount, "kind") - ); +export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { + + const experience: Experience | undefined = tryGetExperience(databaseAccount); + if (experience) { + return experience.shortName; + } + // Must be some new kind of resource that we aren't aware of. Try to get a decent label + const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); + const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; + const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); + return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); + } -export function tryGetExperience( - resource: DatabaseAccountGetResults -): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if ( - resource.capabilities?.find((cap) => cap.name === "EnableGremlin") - ) { - return GremlinExperience; - } else if ( - resource.capabilities?.find((cap) => cap.name === "EnableTable") - ) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; +export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { + // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type + if (resource.kind === DBAccountKind.MongoDB) { + return MongoExperience; + } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { + return GremlinExperience; + } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { + return TableExperience; + } else if (resource.capabilities?.length === 0) { + return CoreExperience; + } + + return undefined; } export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; + /** + * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) + */ + api: API; - longName: string; - shortName: string; - description?: string; + longName: string; + shortName: string; + description?: string; - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; + // These properties are what the portal actually looks at to determine the difference between APIs + kind?: DBAccountKind; + capability?: CapabilityName; - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; + // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) + tag?: string; } -export function getExperienceQuickPicks( - attached?: boolean -): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map((exp) => - getExperienceQuickPickForAttached(exp.api) - ); - } else { - return experiencesArray.map((exp) => getExperienceQuickPick(exp.api)); - } +export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { + if (attached) { + return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); + } else { + return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); + } } -export function getCosmosExperienceQuickPicks( - attached?: boolean -): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map((exp) => - getExperienceQuickPickForAttached(exp.api) - ); - } else { - return cosmosExperiencesArray.map((exp) => - getExperienceQuickPick(exp.api) - ); - } +export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { + if (attached) { + return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); + } else { + return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); + } } -export function getExperienceQuickPick( - api: API -): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; +export function getExperienceQuickPick(api: API): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.longName, description: exp.description, data: exp }; } -export function getExperienceQuickPickForAttached( - api: API -): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; +export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.shortName, description: exp.description, data: exp }; } // Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" // Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { - api: API.Core, - longName: "Core", - description: "(SQL)", - shortName: "SQL", - kind: DBAccountKind.GlobalDocumentDB, - tag: "Core (SQL)", -} as const; -export const MongoExperience: Experience = { - api: API.MongoDB, - longName: "Azure Cosmos DB for MongoDB API", - shortName: "MongoDB", - kind: DBAccountKind.MongoDB, - tag: "Azure Cosmos DB for MongoDB API", -} as const; -export const TableExperience: Experience = { - api: API.Table, - longName: "Azure Table", - shortName: "Table", - kind: DBAccountKind.GlobalDocumentDB, - capability: "EnableTable", - tag: "Azure Table", -} as const; -export const GremlinExperience: Experience = { - api: API.Graph, - longName: "Gremlin", - description: "(graph)", - shortName: "Gremlin", - kind: DBAccountKind.GlobalDocumentDB, - capability: "EnableGremlin", - tag: "Gremlin (graph)", -} as const; -const PostgresSingleExperience: Experience = { - api: API.PostgresSingle, - longName: "PostgreSQL Single Server", - shortName: "PostgreSQLSingle", -}; -const PostgresFlexibleExperience: Experience = { - api: API.PostgresFlexible, - longName: "PostgreSQL Flexible Server", - shortName: "PostgreSQLFlexible", -}; - -const cosmosExperiencesArray: Experience[] = [ - CoreExperience, - MongoExperience, - TableExperience, - GremlinExperience, -]; -const experiencesArray: Experience[] = [ - ...cosmosExperiencesArray, - PostgresSingleExperience, - PostgresFlexibleExperience, -]; -const experiencesMap = new Map( - experiencesArray.map((info: Experience): [API, Experience] => [ - info.api, - info, - ]) -); +export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; +export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; +export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; +export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; +const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; +const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; + +const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; +const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; +const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); diff --git a/Source/DatabasesFileSystem.ts b/Source/DatabasesFileSystem.ts index da2073ac0..93c2b4938 100644 --- a/Source/DatabasesFileSystem.ts +++ b/Source/DatabasesFileSystem.ts @@ -3,13 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeFileSystem, - AzExtTreeItem, - DialogResponses, - IActionContext, - UserCancelledError, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; import { FileChangeType } from "vscode-languageclient"; import { ext } from "./extensionVariables"; @@ -18,103 +12,66 @@ import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; import { getNodeEditorLabel } from "./utils/vscodeUtils"; export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; + id: string; + filePath: string; + cTime: number; + mTime: number; + getFileContent(context: IActionContext): Promise; + writeFileContent(context: IActionContext, data: string): Promise; } export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = "azureDatabases"; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; + public static scheme: string = 'azureDatabases'; + public scheme: string = DatabasesFileSystem.scheme; + private _showSaveConfirmation: boolean = true; - public async statImpl( - context: IActionContext, - node: IEditableTreeItem - ): Promise { - const size: number = Buffer.byteLength( - await node.getFileContent(context) - ); - return { - type: FileType.File, - ctime: node.cTime, - mtime: node.mTime, - size, - }; - } + public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { + const size: number = Buffer.byteLength(await node.getFileContent(context)); + return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; + } - public async readFileImpl( - context: IActionContext, - node: IEditableTreeItem - ): Promise { - return Buffer.from(await node.getFileContent(context)); - } + public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { + return Buffer.from(await node.getFileContent(context)); + } - public async writeFileImpl( - context: IActionContext, - node: IEditableTreeItem, - content: Uint8Array, - _originalUri: Uri - ): Promise { - const showSavePromptKey: string = "showSavePrompt"; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = "cosmosDB"; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if ( - this._showSaveConfirmation && - getWorkspaceSetting(showSavePromptKey, undefined, prefix) - ) { - const message: string = localize( - "saveConfirmation", - 'Saving "{0}" will update the entity "{1}" to the cloud.', - node.filePath, - nodeEditorLabel - ); - const result: MessageItem | undefined = - await context.ui.showWarningMessage( - message, - { stepName: "writeFile" }, - DialogResponses.upload, - DialogResponses.alwaysUpload, - DialogResponses.dontUpload - ); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError("dontUpload"); - } - } + public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { + const showSavePromptKey: string = 'showSavePrompt'; + // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" + const prefix: string = 'cosmosDB'; + const nodeEditorLabel: string = getNodeEditorLabel(node); + if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { + const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); + const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); + if (result === DialogResponses.alwaysUpload) { + await updateGlobalSetting(showSavePromptKey, false, prefix); + } else if (result === DialogResponses.dontUpload) { + throw new UserCancelledError('dontUpload'); + } + } - await node.writeFileContent(context, content.toString()); - await node.refresh(context); + await node.writeFileContent(context, content.toString()); + await node.refresh(context); - const updatedMessage: string = localize( - "updatedEntity", - 'Updated entity "{0}".', - nodeEditorLabel - ); - ext.outputChannel.appendLog(updatedMessage); - } + const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); + ext.outputChannel.appendLog(updatedMessage); + } - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } + public getFilePath(node: IEditableTreeItem): string { + return node.filePath; + } - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } + public async updateWithoutPrompt(uri: Uri): Promise { + const textDoc = await workspace.openTextDocument(uri); + this._showSaveConfirmation = false; + try { + await textDoc.save(); + } finally { + this._showSaveConfirmation = true; + } + } - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } + public fireChangedEvent(node: IEditableTreeItem): void { + node.mTime = Date.now(); + this.fireSoon({ type: FileChangeType.Changed, item: node }); + } } diff --git a/Source/ParsedConnectionString.ts b/Source/ParsedConnectionString.ts index 1619d6390..99654ef5a 100644 --- a/Source/ParsedConnectionString.ts +++ b/Source/ParsedConnectionString.ts @@ -4,27 +4,25 @@ *--------------------------------------------------------------------------------------------*/ export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; + public abstract readonly hostName: string; + public abstract readonly port: string; - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; + /** + * databaseName may be undefined if this is an account-level connection string + */ + public readonly databaseName: string | undefined; + public readonly connectionString: string; - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } + constructor(connectionString: string, databaseName: string | undefined) { + this.connectionString = connectionString; + this.databaseName = databaseName; + } - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } + public get accountId(): string { + return `${this.hostName}:${this.port}`; + } - public get fullId(): string { - return `${this.accountId}${ - this.databaseName ? "/" + this.databaseName : "" - }`; - } + public get fullId(): string { + return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; + } } diff --git a/Source/azureAccountUtils.ts b/Source/azureAccountUtils.ts index fbd474ae3..7f37da4cd 100644 --- a/Source/azureAccountUtils.ts +++ b/Source/azureAccountUtils.ts @@ -9,32 +9,23 @@ import { getApiExport } from "./getExtensionApi"; const azureAccountExtensionId = "ms-vscode.azure-account"; type AzureSession = { - userId: string; + userId: string; }; /** * @returns The user session of the signed-in azure account. */ -export async function getAzureAdUserSession(): Promise< - AzureSession | undefined -> { - const azureAccountExport = (await getApiExport( - azureAccountExtensionId - )) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; +export async function getAzureAdUserSession(): Promise { + const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; + return azureAccountExport.sessions?.[0]; } /** * Gets a function that can request an access token for a specified scope for the signed-in azure account. */ -export function getTokenFunction( - credentials: AzExtServiceClientCredentials, - scope: string -): () => Promise { - return async () => { - const getTokenResult = (await credentials.getToken(scope)) as - | { token: string } - | undefined; - return getTokenResult?.token ?? ""; - }; +export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { + return async () => { + const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; + return getTokenResult?.token ?? ""; + }; } diff --git a/Source/commands/api/DatabaseAccountTreeItemInternal.ts b/Source/commands/api/DatabaseAccountTreeItemInternal.ts index 6a5cebe8a..89a8c1164 100644 --- a/Source/commands/api/DatabaseAccountTreeItemInternal.ts +++ b/Source/commands/api/DatabaseAccountTreeItemInternal.ts @@ -3,146 +3,104 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { API } from "../../AzureDBExperiences"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { ParsedPostgresConnectionString } from "../../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { nonNullProp } from "../../utils/nonNull"; -import { DatabaseAccountTreeItem } from "../../vscode-cosmosdb.api"; +import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { API } from '../../AzureDBExperiences'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { nonNullProp } from '../../utils/nonNull'; +import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; -export class DatabaseAccountTreeItemInternal - implements DatabaseAccountTreeItem -{ - protected _parsedCS: ParsedConnectionString; - private _accountNode: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem - | undefined; +export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { + protected _parsedCS: ParsedConnectionString; + private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; - constructor( - parsedCS: ParsedConnectionString, - accountNode?: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem - ) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } + constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { + this._parsedCS = parsedCS; + this._accountNode = accountNode; + } - public get connectionString(): string { - return this._parsedCS.connectionString; - } + public get connectionString(): string { + return this._parsedCS.connectionString; + } - public get hostName(): string { - return this._parsedCS.hostName; - } + public get hostName(): string { + return this._parsedCS.hostName; + } - public get port(): string { - return this._parsedCS.port; - } + public get port(): string { + return this._parsedCS.port; + } - public get azureData(): - | { accountName: string; accountId: string } - | undefined { - if ( - this._accountNode instanceof MongoAccountTreeItem || - this._accountNode instanceof DocDBAccountTreeItemBase - ) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp( - this._accountNode.databaseAccount, - "name" - ), - accountId: this._accountNode.fullId, - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId, - }; - } - } - return undefined; - } + public get azureData(): { accountName: string, accountId: string } | undefined { + if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { + if (this._accountNode?.databaseAccount) { + return { + accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), + accountId: this._accountNode.fullId + }; + } + } else if (this._accountNode instanceof PostgresServerTreeItem) { + if (this._accountNode.azureName) { + return { + accountName: this._accountNode.azureName, + accountId: this._accountNode.fullId + }; + } + } + return undefined; + } - public get docDBData(): - | { masterKey: string; documentEndpoint: string } - | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey, - }; - } else { - return undefined; - } - } + public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { + if (this._accountNode instanceof DocDBAccountTreeItemBase) { + return { + documentEndpoint: this._accountNode.root.endpoint, + masterKey: this._accountNode.root.masterKey + }; + } else { + return undefined; + } + } - public get postgresData(): - | { username: string | undefined; password: string | undefined } - | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password, - }; - } else { - return undefined; - } - } + public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { + if (this._parsedCS instanceof ParsedPostgresConnectionString) { + const connectionString = this._parsedCS; + return { + username: connectionString.username, + password: connectionString.password + }; + } else { + return undefined; + } + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling( - "api.dbAccount.reveal", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal( - await this.getAccountNode(context) - ); - } - ); - } + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); + }); + } - protected async getAccountNode( - context: IActionContext - ): Promise< - MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem - > { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if ( - this._parsedCS instanceof ParsedPostgresConnectionString - ) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = - await ext.attachedAccountsNode.attachConnectionString( - context, - this.connectionString, - apiType - ); - } + protected async getAccountNode(context: IActionContext): Promise { + // If this._accountNode is undefined, attach a new node based on connection string + if (!this._accountNode) { - return this._accountNode; - } + let apiType: API; + if (this._parsedCS instanceof ParsedMongoConnectionString) { + apiType = API.MongoDB; + } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { + apiType = API.PostgresSingle; + } else { + apiType = API.Core; + } + this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); + } + + return this._accountNode; + } } diff --git a/Source/commands/api/DatabaseTreeItemInternal.ts b/Source/commands/api/DatabaseTreeItemInternal.ts index 8fa8389b2..9d6b0d140 100644 --- a/Source/commands/api/DatabaseTreeItemInternal.ts +++ b/Source/commands/api/DatabaseTreeItemInternal.ts @@ -3,71 +3,40 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { DatabaseTreeItem } from "../../vscode-cosmosdb.api"; -import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; +import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -export class DatabaseTreeItemInternal - extends DatabaseAccountTreeItemInternal - implements DatabaseTreeItem -{ - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; +export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { + public databaseName: string; + private _dbNode: AzExtTreeItem | undefined; - constructor( - parsedCS: ParsedConnectionString, - databaseName: string, - accountNode?: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem, - dbNode?: - | MongoDatabaseTreeItem - | DocDBDatabaseTreeItemBase - | PostgresDatabaseTreeItem - ) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } + constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { + super(parsedCS, accountNode); + this.databaseName = databaseName; + this._dbNode = dbNode; + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling( - "api.db.reveal", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const accountNode: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem = - await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = - await ext.rgApi.workspaceResourceTree.findTreeItem( - databaseId, - context - ); - } + const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); + if (!this._dbNode) { + const databaseId = `${accountNode.fullId}/${this.databaseName}`; + this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); + } - await ext.rgApi.workspaceResourceTreeView.reveal( - this._dbNode || accountNode - ); - } - ); - } + await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); + }); + } } diff --git a/Source/commands/api/apiCache.ts b/Source/commands/api/apiCache.ts index 9020478fd..30da342aa 100644 --- a/Source/commands/api/apiCache.ts +++ b/Source/commands/api/apiCache.ts @@ -3,68 +3,44 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParsedDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; -import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { - ParsedPostgresConnectionString, - parsePostgresConnectionString, -} from "../../postgres/postgresConnectionStrings"; -import { - DatabaseAccountTreeItem, - DatabaseTreeItem, -} from "../../vscode-cosmosdb.api"; +import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; +import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; +import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; /** * This cache is used to speed up api calls from other extensions to the Cosmos DB extension * For now, it only helps on a per-session basis */ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = - new Map(); +const sessionCache: Map = new Map(); -export function cacheTreeItem( - parsedCS: ParsedConnectionString, - treeItem: DatabaseAccountTreeItem | DatabaseTreeItem -): void { - sessionCache.set(parsedCS.fullId, treeItem); +export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { + sessionCache.set(parsedCS.fullId, treeItem); } -export function tryGetTreeItemFromCache( - parsedCS: ParsedConnectionString -): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); +export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { + return sessionCache.get(parsedCS.fullId); } -export function removeTreeItemFromCache( - expected: ParsedConnectionString -): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString( - value.connectionString, - value.hostName, - value.port, - undefined - ); - } else { - actual = new ParsedDocDBConnectionString( - value.connectionString, - value.hostName, - value.port, - undefined - ); - } - if (actual && actual.accountId === expected.accountId) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } +export function removeTreeItemFromCache(expected: ParsedConnectionString): void { + if (!expected.databaseName) { + // If parsedCS represents an account, remove the account and any databases that match that account + for (const [key, value] of sessionCache.entries()) { + let actual: ParsedConnectionString | undefined; + if (expected instanceof ParsedPostgresConnectionString) { + actual = parsePostgresConnectionString(value.connectionString); + } else if (expected instanceof ParsedMongoConnectionString) { + actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); + } else { + actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); + } + if (actual && (actual.accountId === expected.accountId)) { + sessionCache.delete(key); + } + } + } else { + sessionCache.delete(expected.fullId); + } } diff --git a/Source/commands/api/findTreeItem.ts b/Source/commands/api/findTreeItem.ts index d7e0f0d01..088413e52 100644 --- a/Source/commands/api/findTreeItem.ts +++ b/Source/commands/api/findTreeItem.ts @@ -3,223 +3,144 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { - createPostgresConnectionString, - parsePostgresConnectionString, -} from "../../postgres/postgresConnectionStrings"; -import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { SubscriptionTreeItem } from "../../tree/SubscriptionTreeItem"; -import { nonNullProp } from "../../utils/nonNull"; -import { - DatabaseAccountTreeItem, - DatabaseTreeItem, - TreeItemQuery, -} from "../../vscode-cosmosdb.api"; -import { cacheTreeItem, tryGetTreeItemFromCache } from "./apiCache"; -import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; - -export async function findTreeItem( - query: TreeItemQuery -): Promise { - return await callWithTelemetryAndErrorHandling( - "api.findTreeItem", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString( - postgresData.hostName, - postgresData.port, - postgresData.username, - postgresData.password, - postgresData.databaseName - ); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, "connectionString"); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = - await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = - tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = - await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts( - attachedDbAccounts, - parsedCS, - context, - maxTime - ); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = - await rootNode.getCachedChildren(context); - result = await searchDbAccounts( - dbAccounts, - parsedCS, - context, - maxTime - ); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal( - parsedCS, - parsedCS.databaseName - ); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - } - ); +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; +import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; +import { nonNullProp } from '../../utils/nonNull'; +import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; +import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; +import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; + +export async function findTreeItem(query: TreeItemQuery): Promise { + return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + + let parsedCS: ParsedConnectionString; + if (query.postgresData) { + const postgresData = query.postgresData; + const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); + parsedCS = parsePostgresConnectionString(connectionString); + } else { + const connectionString = nonNullProp(query, 'connectionString'); + if (/^mongodb[^:]*:\/\//i.test(connectionString)) { + parsedCS = await parseMongoConnectionString(connectionString); + } else if (/^postgres:\/\//i.test(connectionString)) { + parsedCS = parsePostgresConnectionString(connectionString); + } else { + parsedCS = parseDocDBConnectionString(connectionString); + } + } + + const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account + + // 1. Get result from cache if possible + let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); + + // 2. Search attached accounts (do this before subscriptions because it's faster) + if (!result) { + const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); + result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); + } + + // 3. Search subscriptions + if (!result) { + const rootNodes = await ext.rgApi.appResourceTree.getChildren(); + for (const rootNode of rootNodes) { + if (Date.now() > maxTime) { + break; + } + + if (rootNode instanceof SubscriptionTreeItem) { + const dbAccounts = await rootNode.getCachedChildren(context); + result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); + if (result) { + break; + } + } + } + } + + // 4. If all else fails, just attach a new node + if (!result) { + if (parsedCS.databaseName) { + result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); + } else { + result = new DatabaseAccountTreeItemInternal(parsedCS); + } + } + + cacheTreeItem(parsedCS, result); + + return result; + }); } -async function searchDbAccounts( - dbAccounts: AzExtTreeItem[], - expected: ParsedConnectionString, - context: IActionContext, - maxTime: number -): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString( - dbAccount.connectionString - ); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ( - (db instanceof MongoDatabaseTreeItem || - db instanceof DocDBDatabaseTreeItemBase) && - expected.databaseName === db.databaseName - ) { - return new DatabaseTreeItemInternal( - expected, - expected.databaseName, - dbAccount, - db - ); - } - if ( - db instanceof PostgresDatabaseTreeItem && - dbAccount instanceof PostgresServerTreeItem && - expected.databaseName === db.databaseName - ) { - const fullConnectionString = - await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal( - fullConnectionString, - expected.databaseName, - dbAccount, - db - ); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = - await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal( - fullConnectionString, - expected.databaseName, - dbAccount - ); - } else { - return new DatabaseTreeItemInternal( - expected, - expected.databaseName, - dbAccount - ); - } - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = - await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal( - fullConnectionString, - dbAccount - ); - } else { - return new DatabaseAccountTreeItemInternal( - expected, - dbAccount - ); - } - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; +async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { + try { + for (const dbAccount of dbAccounts) { + if (Date.now() > maxTime) { + return undefined; + } + + let actual: ParsedConnectionString; + if (dbAccount instanceof MongoAccountTreeItem) { + actual = await parseMongoConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof DocDBAccountTreeItemBase) { + actual = parseDocDBConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof PostgresServerTreeItem) { + actual = dbAccount.partialConnectionString; + } else { + return undefined; + } + + if (expected.accountId === actual.accountId) { + if (expected.databaseName) { + const dbs = await dbAccount.getCachedChildren(context); + for (const db of dbs) { + if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { + return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); + } + if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { + const fullConnectionString = await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); + } + } + + // We found the right account - just not the db. In this case we can still 'reveal' the account + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); + } else { + return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); + } + + } + + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = await dbAccount.getFullConnectionString(); + return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); + } else { + return new DatabaseAccountTreeItemInternal(expected, dbAccount); + } + + } + } + } catch (error) { + // Swallow all errors to avoid blocking the db account search + // https://github.com/microsoft/vscode-cosmosdb/issues/966 + } + + return undefined; } diff --git a/Source/commands/api/pickTreeItem.ts b/Source/commands/api/pickTreeItem.ts index f67ab039d..dc84ce55a 100644 --- a/Source/commands/api/pickTreeItem.ts +++ b/Source/commands/api/pickTreeItem.ts @@ -3,146 +3,98 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { PickAppResourceOptions } from "@microsoft/vscode-azext-utils/hostapi"; -import { databaseAccountType } from "../../constants"; -import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBDatabaseTreeItem } from "../../docdb/tree/DocDBDatabaseTreeItem"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { GraphDatabaseTreeItem } from "../../graph/tree/GraphDatabaseTreeItem"; -import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { localize } from "../../utils/localize"; -import { - AzureDatabasesApiType, - DatabaseAccountTreeItem, - DatabaseTreeItem, - PickTreeItemOptions, -} from "../../vscode-cosmosdb.api"; -import { cacheTreeItem } from "./apiCache"; -import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; +import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; +import { databaseAccountType } from '../../constants'; +import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; +import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { localize } from '../../utils/localize'; +import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; +import { cacheTreeItem } from './apiCache'; +import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; -const databaseContextValues = [ - MongoDatabaseTreeItem.contextValue, - DocDBDatabaseTreeItem.contextValue, - GraphDatabaseTreeItem.contextValue, - PostgresDatabaseTreeItem.contextValue, -]; +const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case "Mongo": - return MongoDatabaseTreeItem.contextValue; - case "SQL": - return DocDBDatabaseTreeItem.contextValue; - case "Graph": - return GraphDatabaseTreeItem.contextValue; - case "Postgres": - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } + switch (apiType) { + case 'Mongo': + return MongoDatabaseTreeItem.contextValue; + case 'SQL': + return DocDBDatabaseTreeItem.contextValue; + case 'Graph': + return GraphDatabaseTreeItem.contextValue; + case 'Postgres': + return PostgresDatabaseTreeItem.contextValue; + default: + throw new RangeError(`Unsupported api type "${apiType}".`); + } } -export async function pickTreeItem( - pickTreeOptions: PickTreeItemOptions -): Promise { - return await callWithTelemetryAndErrorHandling( - "api.pickTreeItem", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case "Database": - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType - ? pickTreeOptions.apiType.map(getDatabaseContextValue) - : databaseContextValues; - break; - case "DatabaseAccount": - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError( - `Unsupported resource type "${pickTreeOptions.resourceType}".` - ); - } +export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { + return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const pickedItem = await ext.rgApi.pickAppResource( - context, - options - ); + const options: PickAppResourceOptions = {}; + switch (pickTreeOptions.resourceType) { + case 'Database': + options.filter = { type: databaseAccountType }; + options.expectedChildContextValue = pickTreeOptions.apiType ? + pickTreeOptions.apiType.map(getDatabaseContextValue) : + databaseContextValues; + break; + case 'DatabaseAccount': + options.filter = { type: databaseAccountType }; + break; + default: + throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); + } - let parsedCS: ParsedConnectionString; - let accountNode: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem; - let databaseNode: - | MongoDatabaseTreeItem - | DocDBDatabaseTreeItemBase - | PostgresDatabaseTreeItem - | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError( - localize( - "invalidItem", - 'Invalid item "{0}".', - pickedItem.constructor.name - ) - ); - } + const pickedItem = await ext.rgApi.pickAppResource(context, options); - const result = databaseNode - ? new DatabaseTreeItemInternal( - parsedCS, - databaseNode.databaseName, - accountNode, - databaseNode - ) - : new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - } - ); + let parsedCS: ParsedConnectionString; + let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; + let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; + if (pickedItem instanceof MongoAccountTreeItem) { + parsedCS = await parseMongoConnectionString(pickedItem.connectionString); + accountNode = pickedItem; + } else if (pickedItem instanceof DocDBAccountTreeItemBase) { + parsedCS = parseDocDBConnectionString(pickedItem.connectionString); + accountNode = pickedItem; + } else if (pickedItem instanceof PostgresServerTreeItem) { + parsedCS = await pickedItem.getFullConnectionString(); + accountNode = pickedItem; + } else if (pickedItem instanceof MongoDatabaseTreeItem) { + parsedCS = await parseMongoConnectionString(pickedItem.connectionString); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { + parsedCS = parseDocDBConnectionString(pickedItem.connectionString); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof PostgresDatabaseTreeItem) { + parsedCS = await pickedItem.parent.getFullConnectionString(); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else { + throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); + } + + const result = databaseNode ? + new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : + new DatabaseAccountTreeItemInternal(parsedCS, accountNode); + cacheTreeItem(parsedCS, result); + return result; + }); } diff --git a/Source/commands/api/revealTreeItem.ts b/Source/commands/api/revealTreeItem.ts index 185ff340c..d13589351 100644 --- a/Source/commands/api/revealTreeItem.ts +++ b/Source/commands/api/revealTreeItem.ts @@ -3,29 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; import { ext } from "../../extensionVariables"; export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling( - "api.revealTreeItem", - async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem(resourceId, { - ...context, - loadAll: true, - }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { - select: true, - focus: true, - expand: true, - }); - } - } - ); + return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { + const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); + if (node) { + await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); + } + }); } diff --git a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts index d409dcc0a..1ef9ca645 100644 --- a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts @@ -7,13 +7,13 @@ import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } + public async execute(context: IDeleteWizardContext): Promise { + await context.node.deleteTreeItem(context); + } - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } + public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { + return true; + } } diff --git a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts index e20bafa90..762beb96e 100644 --- a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts @@ -1,20 +1,13 @@ /*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - ExecuteActivityContext, - IActionContext, - ISubscriptionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; -export interface IDeleteWizardContext - extends IActionContext, - ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; +export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { + node: AzExtTreeItem; + deletePostgres: boolean; + resourceGroupToDelete?: string; + subscription: ISubscriptionContext; } diff --git a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts index b862cb33e..a90956b30 100644 --- a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts @@ -3,49 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { ext } from "../../extensionVariables"; -import { createCosmosDBClient } from "../../utils/azureClients"; -import { getDatabaseAccountNameFromId } from "../../utils/azureUtils"; -import { localize } from "../../utils/localize"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; +import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { ext } from '../../extensionVariables'; +import { createCosmosDBClient } from '../../utils/azureClients'; +import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; +import { localize } from '../../utils/localize'; +import { IDeleteWizardContext } from './IDeleteWizardContext'; -export async function deleteCosmosDBAccount( - context: IDeleteWizardContext, - node: AzExtTreeItem -): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([ - context, - node.subscription, - ]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait( - resourceGroup, - accountName - ); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: deletingMessage, - }, - async () => { - await deletePromise; - const deleteMessage: string = localize( - "deleteAccountMsg", - `Successfully deleted account "{0}".`, - accountName - ); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - } - ); - } else { - await deletePromise; - } +export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { + const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); + const resourceGroup: string = getResourceGroupFromId(node.fullId); + const accountName: string = getDatabaseAccountNameFromId(node.fullId); + const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); + if (!context.suppressNotification) { + const deletingMessage: string = `Deleting account "${accountName}"...`; + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { + await deletePromise; + const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + }); + } else { + await deletePromise; + } } diff --git a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts index ac6857848..4792710d4 100644 --- a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts @@ -3,51 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - AzureWizard, - DeleteConfirmationStep, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; import { createActivityContext } from "../../utils/activityUtils"; import { localize } from "../../utils/localize"; import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; -export async function deleteDatabaseAccount( - context: IActionContext, - node: AzExtTreeItem, - isPostgres: boolean = false -): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()), - }); - const title = wizardContext.deletePostgres - ? localize("deletePoSer", 'Delete Postgres Server "{0}"', node.label) - : localize("deleteDbAcc", 'Delete Database Account "{0}"', node.label); +export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { + const wizardContext: IDeleteWizardContext = Object.assign(context, { + node, + deletePostgres: isPostgres, + subscription: node.subscription, + ...(await createActivityContext()) + }); - const confirmationMessage = wizardContext.deletePostgres - ? localize( - "deleteAccountConfirm", - 'Are you sure you want to delete server "{0}" and its contents?', - node.label - ) - : localize( - "deleteAccountConfirm", - 'Are you sure you want to delete account "{0}" and its contents?', - node.label - ); + const title = wizardContext.deletePostgres ? + localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : + localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()], - }); + const confirmationMessage = wizardContext.deletePostgres ? + localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : + localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); - await wizard.prompt(); - await wizard.execute(); + const wizard = new AzureWizard(wizardContext, { + title, + promptSteps: [new DeleteConfirmationStep(confirmationMessage)], + executeSteps: [new DatabaseAccountDeleteStep()] + }); + + await wizard.prompt(); + await wizard.execute(); } diff --git a/Source/commands/importDocuments.ts b/Source/commands/importDocuments.ts index 305af31eb..bd4c83e3f 100644 --- a/Source/commands/importDocuments.ts +++ b/Source/commands/importDocuments.ts @@ -3,209 +3,161 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from "@azure/cosmos"; -import { IActionContext, parseError } from "@microsoft/vscode-azext-utils"; -import * as fse from "fs-extra"; -import * as vscode from "vscode"; -import { cosmosMongoFilter, sqlFilter } from "../constants"; -import { DocDBCollectionTreeItem } from "../docdb/tree/DocDBCollectionTreeItem"; -import { ext } from "../extensionVariables"; -import { MongoCollectionTreeItem } from "../mongo/tree/MongoCollectionTreeItem"; -import { nonNullProp, nonNullValue } from "../utils/nonNull"; -import { getRootPath } from "../utils/workspacUtils"; +import { ItemDefinition } from '@azure/cosmos'; +import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import * as vscode from 'vscode'; +import { cosmosMongoFilter, sqlFilter } from '../constants'; +import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; +import { ext } from '../extensionVariables'; +import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; +import { nonNullProp, nonNullValue } from '../utils/nonNull'; +import { getRootPath } from '../utils/workspacUtils'; -export async function importDocuments( - context: IActionContext, - uris: vscode.Uri[] | undefined, - collectionNode: - | MongoCollectionTreeItem - | DocDBCollectionTreeItem - | undefined -): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith(".json")) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog( - `Ignoring the following files which are not json:` - ); - ignoredUris.forEach((uri) => - ext.outputChannel.appendLine(`${uri.fsPath}`) - ); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource< - MongoCollectionTreeItem | DocDBCollectionTreeItem - >(context, { - filter: [cosmosMongoFilter, sqlFilter], - expectedChildContextValue: [ - MongoCollectionTreeItem.contextValue, - DocDBCollectionTreeItem.contextValue, - ], - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents...", - }, - async (progress) => { - uris = nonNullValue(uris, "uris"); - collectionNode = nonNullValue(collectionNode, "collectionNode"); +export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { + if (!uris) { + uris = await askForDocuments(context); + } + const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 + uris = uris.filter((uri) => { + if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { + return true; + } else { + ignoredUris.push(uri); + return false; + } + }); + if (ignoredUris.length) { + ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); + ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); + ext.outputChannel.show(); + } + if (!collectionNode) { + collectionNode = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + sqlFilter + ], + expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] + }); + } + let result: string; + result = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Importing documents..." + }, + async (progress) => { + uris = nonNullValue(uris, 'uris'); + collectionNode = nonNullValue(collectionNode, 'collectionNode'); - progress.report({ - increment: 20, - message: "Parsing documents for errors", - }); - const documents = await parseDocuments(uris); - progress.report({ - increment: 30, - message: "Parsed documents. Importing", - }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo( - collectionNode, - documents - ); - } else { - result = await insertDocumentsIntoDocdb( - collectionNode, - documents, - uris - ); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); + progress.report({ increment: 20, message: "Parsing documents for errors" }); + const documents = await parseDocuments(uris); + progress.report({ increment: 30, message: "Parsed documents. Importing" }); + if (collectionNode instanceof MongoCollectionTreeItem) { + result = await insertDocumentsIntoMongo(collectionNode, documents); + } else { + result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); + } + progress.report({ increment: 50, message: "Finished importing" }); + return result; + } + ); - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); + await collectionNode.refresh(context); + await vscode.window.showInformationMessage(result); } async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"], - }, - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); + const openDialogOptions: vscode.OpenDialogOptions = { + canSelectMany: true, + openLabel: "Import", + filters: { + JSON: ["json"] + } + }; + const rootPath: string | undefined = getRootPath(); + if (rootPath) { + openDialogOptions.defaultUri = vscode.Uri.file(rootPath); + } + return await context.ui.showOpenDialog(openDialogOptions); } // eslint-disable-next-line @typescript-eslint/no-explicit-any async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog( - "Errors found in documents listed below. Please fix these." - ); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error( - `Errors found in some documents. Please see the output, fix these and try again.` - ); - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let documents: any[] = []; + let errorFoundFlag: boolean = false; + for (const uri of uris) { + let parsed; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + parsed = await fse.readJSON(uri.fsPath); + } catch (e) { + if (!errorFoundFlag) { + errorFoundFlag = true; + ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); + ext.outputChannel.show(); + } + const err = parseError(e); + ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); + } + if (parsed) { + if (Array.isArray(parsed)) { + documents = documents.concat(parsed); + } else { + documents.push(parsed); + } + } + } + if (errorFoundFlag) { + throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); + } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return documents; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb( - collectionNode: DocDBCollectionTreeItem, - documents: any[], - uris: vscode.Uri[] -): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if ( - !collectionNode.documentsTreeItem.documentHasPartitionKey(document) - ) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog( - `The following documents do not contain the required partition key:` - ); - erroneousFiles.forEach((file) => - ext.outputChannel.appendLine(file.path) - ); - ext.outputChannel.show(); - throw new Error( - `See output for list of documents that do not contain the partition key '${ - nonNullProp(collectionNode, "partitionKey").paths[0] - }' required by collection '${collectionNode.label}'` - ); - } - for (const document of documents) { - const retrieved: ItemDefinition = - await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; +async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { + const ids: string[] = []; + let i = 0; + const erroneousFiles: vscode.Uri[] = []; + for (i = 0; i < documents.length; i++) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const document: ItemDefinition = documents[i]; + if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { + erroneousFiles.push(uris[i]); + } + } + if (erroneousFiles.length) { + ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); + erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); + ext.outputChannel.show(); + throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); + } + for (const document of documents) { + const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); + if (retrieved.id) { + ids.push(retrieved.id); + } + } + const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; + for (const id of ids) { + ext.outputChannel.appendLine(`Inserted document: ${id}`); + } + return result; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo( - node: MongoCollectionTreeItem, - documents: any[] -): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; +async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { + let output = ""; + const parsed = await node.collection.insertMany(documents); + if (parsed.result && parsed.result.ok) { + output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; + for (const inserted of Object.values(parsed.insertedIds)) { + ext.outputChannel.appendLine(`Inserted document: ${inserted}`); + } + } + return output; } diff --git a/Source/constants.ts b/Source/constants.ts index 4d43ec018..0e6a4a14e 100644 --- a/Source/constants.ts +++ b/Source/constants.ts @@ -5,62 +5,47 @@ export const isWindows: boolean = /^win/.test(process.platform); -import * as assert from "assert"; -import * as fs from "fs"; -import * as path from "path"; -import { - CoreExperience, - GremlinExperience, - MongoExperience, - TableExperience, -} from "./AzureDBExperiences"; -import { ext } from "./extensionVariables"; +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as path from 'path'; +import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; +import { ext } from './extensionVariables'; export namespace Links { - export const LocalConnectionDebuggingTips: string = - "https://aka.ms/AA5zah5"; + export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; } export interface IThemedIconPath { - light: string; - dark: string; + light: string; + dark: string; } export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), "icons", "light", iconName), - dark: path.join(getResourcesPath(), "icons", "dark", iconName), - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), 'icons', 'light', iconName), + dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) + }; + assert(fs.existsSync(a.light)); + return a; } export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join( - getResourcesPath(), - "icons", - "theme-agnostic", - iconName - ), - dark: path.join( - getResourcesPath(), - "icons", - "theme-agnostic", - iconName - ), - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), + dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) + }; + assert(fs.existsSync(a.light)); + return a; } export function getResourcesPath(): string { - return ext.context.asAbsolutePath("resources"); + return ext.context.asAbsolutePath('resources'); } export const doubleClickDebounceDelay = 500; //milliseconds -export const defaultStoredProcedure = `function sample(prefix) { +export const defaultStoredProcedure = + `function sample(prefix) { var collection = getContext().getCollection(); // Query documents and take 1st item. @@ -85,69 +70,67 @@ export const defaultStoredProcedure = `function sample(prefix) { }); if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};`; +};` ; -export const emulatorPassword = - "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; +export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; // https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = "test"; +export const testDb: string = 'test'; -export const connectedPostgresKey: string = - "ms-azuretools.vscode-azuredatabases.connectedPostgresDB"; -export const postgresLanguageId: string = "postgres"; +export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; +export const postgresLanguageId: string = 'postgres'; export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = "query"; -export const postgresDefaultPort = "5432"; -export const postgresDefaultDatabase = "postgres"; -export const SERVERLESS_CAPABILITY_NAME = "EnableServerless"; +export const postgresBaseFileName: string = 'query'; +export const postgresDefaultPort = '5432'; +export const postgresDefaultDatabase = 'postgres'; +export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; -export const databaseAccountType = "Microsoft.DocumentDB/databaseAccounts"; +export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag, - }, + type: databaseAccountType, + kind: MongoExperience.kind, + tags: { + defaultExperience: mongoDefaultExperienceTag + } }; -export const gremlinDefaultExperienceTag = "Gremlin (graph)"; +export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag, - }, + type: databaseAccountType, + kind: GremlinExperience.kind, + tags: { + defaultExperience: gremlinDefaultExperienceTag + } }; -export const tableDefaultExperienceTag = "Azure Table"; +export const tableDefaultExperienceTag = 'Azure Table'; export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag, - }, + type: databaseAccountType, + kind: TableExperience.kind, + tags: { + defaultExperience: tableDefaultExperienceTag + } }; -export const sqlDefaultExperienceTag = "Core (SQL)"; +export const sqlDefaultExperienceTag = 'Core (SQL)'; export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag, - }, + type: databaseAccountType, + kind: CoreExperience.kind, + tags: { + defaultExperience: sqlDefaultExperienceTag + } }; export const postgresFlexibleFilter = { - type: "Microsoft.DBforPostgreSQL/flexibleServers", + type: 'Microsoft.DBforPostgreSQL/flexibleServers' }; export const postgresSingleFilter = { - type: "Microsoft.DBForPostgreSQL/servers", + type: 'Microsoft.DBForPostgreSQL/servers' }; diff --git a/Source/docdb/docDBConnectionStrings.ts b/Source/docdb/docDBConnectionStrings.ts index 3389eeea4..946490d21 100644 --- a/Source/docdb/docDBConnectionStrings.ts +++ b/Source/docdb/docDBConnectionStrings.ts @@ -3,64 +3,40 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as url from "url"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullProp } from "../utils/nonNull"; +import * as url from 'url'; +import { ParsedConnectionString } from '../ParsedConnectionString'; +import { nonNullProp } from '../utils/nonNull'; -export function parseDocDBConnectionString( - connectionString: string -): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString( - connectionString, - "AccountEndpoint" - ); - const masterKey = getPropertyFromConnectionString( - connectionString, - "AccountKey" - ); - const databaseName = getPropertyFromConnectionString( - connectionString, - "Database" - ); - if (!endpoint || !masterKey) { - throw new Error("Invalid Document DB connection string."); - } - return new ParsedDocDBConnectionString( - connectionString, - endpoint, - masterKey, - databaseName - ); +export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { + const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); + const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); + const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); + if (!endpoint || !masterKey) { + throw new Error('Invalid Document DB connection string.'); + } + return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); } -function getPropertyFromConnectionString( - connectionString: string, - property: string -): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, "i"); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; +function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { + const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); + const match = connectionString.match(regexp); + return match ? match[1] : undefined; } export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - public readonly documentEndpoint: string; - public readonly masterKey: string; + public readonly documentEndpoint: string; + public readonly masterKey: string; - constructor( - connectionString: string, - endpoint: string, - masterKey: string, - databaseName: string | undefined - ) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; + constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { + super(connectionString, databaseName); + this.documentEndpoint = endpoint; + this.masterKey = masterKey; - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, "hostname"); - this.port = nonNullProp(parsedEndpoint, "port"); - } + const parsedEndpoint = url.parse(endpoint); + this.hostName = nonNullProp(parsedEndpoint, 'hostname'); + this.port = nonNullProp(parsedEndpoint, 'port'); + } } diff --git a/Source/docdb/getCosmosClient.ts b/Source/docdb/getCosmosClient.ts index f422ec3c2..3b285fc9c 100644 --- a/Source/docdb/getCosmosClient.ts +++ b/Source/docdb/getCosmosClient.ts @@ -6,33 +6,14 @@ import { CosmosClient } from "@azure/cosmos"; import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; import * as https from "https"; -import * as vscode from "vscode"; +import * as vscode from 'vscode'; import { ext } from "../extensionVariables"; -export function getCosmosClient( - endpoint: string, - key: string, - isEmulator: boolean | undefined -): CosmosClient { - const vscodeStrictSSL: boolean | undefined = vscode.workspace - .getConfiguration() - .get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace - .getConfiguration() - .get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { - enableEndpointDiscovery: - enableEndpointDiscovery === undefined - ? true - : enableEndpointDiscovery, - }; - return new CosmosClient({ - endpoint, - key, - userAgentSuffix: appendExtensionUserAgent(), - agent: new https.Agent({ - rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL, - }), - connectionPolicy: connectionPolicy, - }); +export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { + + const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); + const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); + const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; + return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); + } diff --git a/Source/docdb/registerDocDBCommands.ts b/Source/docdb/registerDocDBCommands.ts index a8f29c69d..5eb7545e4 100644 --- a/Source/docdb/registerDocDBCommands.ts +++ b/Source/docdb/registerDocDBCommands.ts @@ -3,12 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - IActionContext, - ITreeItemPickerContext, - registerCommandWithTreeNodeUnwrapping, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; import { commands } from "vscode"; import { doubleClickDebounceDelay, sqlFilter } from "../constants"; import { ext } from "../extensionVariables"; @@ -21,170 +16,89 @@ import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeI import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBDatabase", - createDocDBDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBCollection", - createDocDBCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBDocument", - async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDocumentsTreeItem.contextValue - ); - } - const documentNode = ( - await node.createChild(context) - ); - await commands.executeCommand( - "cosmosDB.openDocument", - documentNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBStoredProcedure", - async ( - context: IActionContext, - node?: DocDBStoredProceduresTreeItem - ) => { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBStoredProceduresTreeItem.contextValue - ); - } - const childNode = await node.createChild(context); - await commands.executeCommand( - "cosmosDB.openStoredProcedure", - childNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBDatabase", - deleteDocDBDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBCollection", - deleteDocDBCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openStoredProcedure", - async ( - context: IActionContext, - node?: DocDBStoredProcedureTreeItem - ) => { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBStoredProcedureTreeItem.contextValue - ); - } - await ext.fileSystem.showTextDocument(node); - }, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBDocument", - async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDocumentTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBStoredProcedure", - async ( - context: IActionContext, - node?: DocDBStoredProcedureTreeItem - ) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBStoredProcedureTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { + if (!node) { + node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); + } + const documentNode = await node.createChild(context); + await commands.executeCommand("cosmosDB.openDocument", documentNode); + + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { + if (!node) { + node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); + } + const childNode = await node.createChild(context); + await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); + + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { + if (!node) { + node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); + } + await ext.fileSystem.showTextDocument(node); + }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); + + } + await node.deleteTreeItem(context); + }); } -export async function createDocDBDatabase( - context: IActionContext, - node?: DocDBAccountTreeItem -): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = ( - await node.createChild(context) - ); - await databaseNode.createChild(context); +export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { + if (!node) { + node = await pickDocDBAccount(context); + } + const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); + await databaseNode.createChild(context); } -export async function createDocDBCollection( - context: IActionContext, - node?: DocDBDatabaseTreeItem -): Promise { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDatabaseTreeItem.contextValue - ); - } - await node.createChild(context); +export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { + if (!node) { + node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); + } + await node.createChild(context); } -export async function deleteDocDBDatabase( - context: IActionContext, - node?: DocDBDatabaseTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDatabaseTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); +export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); + } + await node.deleteTreeItem(context); } -export async function deleteDocDBCollection( - context: IActionContext, - node?: DocDBCollectionTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBCollectionTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); +export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); + } + await node.deleteTreeItem(context); } -async function pickDocDBAccount( - context: IActionContext, - expectedContextValue?: string | RegExp | (string | RegExp)[] -): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [sqlFilter], - expectedChildContextValue: expectedContextValue, - }); +async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [ + sqlFilter + ], + expectedChildContextValue: expectedContextValue + }); } diff --git a/Source/docdb/tree/DocDBAccountTreeItem.ts b/Source/docdb/tree/DocDBAccountTreeItem.ts index 242af5546..0cee7ed06 100644 --- a/Source/docdb/tree/DocDBAccountTreeItem.ts +++ b/Source/docdb/tree/DocDBAccountTreeItem.ts @@ -3,37 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseDefinition, Resource } from "@azure/cosmos"; -import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { DatabaseDefinition, Resource } from '@azure/cosmos'; +import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; +import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; +import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; +import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBDocumentServer"; + public contextValue: string = DocDBAccountTreeItem.contextValue; - public initChild( - resource: DatabaseDefinition & Resource - ): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } + public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { + this.valuesToMask.push(resource._rid, resource._self); + return new DocDBDatabaseTreeItem(this, resource); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case DocDBDatabaseTreeItem.contextValue: + case DocDBCollectionTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case DocDBDocumentsTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/docdb/tree/DocDBAccountTreeItemBase.ts b/Source/docdb/tree/DocDBAccountTreeItemBase.ts index 2984b29ef..da9eec6b7 100644 --- a/Source/docdb/tree/DocDBAccountTreeItemBase.ts +++ b/Source/docdb/tree/DocDBAccountTreeItemBase.ts @@ -3,139 +3,93 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { - CosmosClient, - DatabaseDefinition, - DatabaseResponse, - FeedOptions, - QueryIterator, - Resource, -} from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - ICreateChildImplContext, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; -import { - SERVERLESS_CAPABILITY_NAME, - getThemeAgnosticIconPath, -} from "../../constants"; -import { nonNullProp } from "../../utils/nonNull"; -import { rejectOnTimeout } from "../../utils/timeout"; -import { getCosmosClient } from "../getCosmosClient"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; +import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; +import { nonNullProp } from '../../utils/nonNull'; +import { rejectOnTimeout } from '../../utils/timeout'; +import { getCosmosClient } from '../getCosmosClient'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; /** * This class provides common logic for DocumentDB, Graph, and Table accounts * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase< - DatabaseDefinition & Resource -> { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; +export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { + public readonly label: string; + public readonly childTypeLabel: string = "Database"; - constructor( - parent: AzExtParentTreeItem, - id: string, - label: string, - endpoint: string, - masterKey: string, - isEmulator: boolean | undefined, - readonly databaseAccount?: DatabaseAccountGetResults - ) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => - getCosmosClient(endpoint, masterKey, isEmulator), - }; - this.valuesToMask.push(id, endpoint, masterKey); - } + constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { + super(parent); + this.id = id; + this.label = label; + this.root = { + endpoint, + masterKey, + isEmulator, + getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) + }; - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } + this.valuesToMask.push(id, endpoint, masterKey); + } - public get iconPath(): - | string - | vscode.Uri - | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath("CosmosDBAccount.svg"); - } + public get connectionString(): string { + return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; + } - public get isServerless(): boolean { - return this.databaseAccount?.capabilities - ? this.databaseAccount.capabilities.some( - (cap) => cap.name === SERVERLESS_CAPABILITY_NAME - ) - : false; - } + public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath('CosmosDBAccount.svg'); + } - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return client.databases.readAll(feedOptions); - } + public get isServerless(): boolean { + return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - validateInput: validateDatabaseName, - stepName: "createDatabase", - }); + } - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ - id: databaseName, - }); - return this.initChild(nonNullProp(database, "resource")); - } + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return client.databases.readAll(feedOptions); + } - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = - "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout( - 2000, - () => super.loadMoreChildrenImpl(clearCache), - unableToReachEmulatorMessage - ); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } + public async createChildImpl(context: ICreateChildImplContext): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: 'Database Name', + validateInput: validateDatabaseName, + stepName: 'createDatabase' + }); - public async deleteTreeItemImpl( - context: IDeleteWizardContext - ): Promise { - await deleteCosmosDBAccount(context, this); - } + const client = this.root.getCosmosClient(); + const database: DatabaseResponse = await client.databases.create({ id: databaseName }); + return this.initChild(nonNullProp(database, 'resource')); + } + + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (this.root.isEmulator) { + const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; + return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); + } else { + return await super.loadMoreChildrenImpl(clearCache); + } + } + + public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { + await deleteCosmosDBAccount(context, this); + } } function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; + if (!name || name.length < 1 || name.length > 255) { + return "Name has to be between 1 and 255 chars long"; + } + if (name.endsWith(" ")) { + return "Database name cannot end with space"; + } + if (/[/\\?#=]/.test(name)) { + return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBCollectionTreeItem.ts b/Source/docdb/tree/DocDBCollectionTreeItem.ts index 8849bee34..987bbe3b4 100644 --- a/Source/docdb/tree/DocDBCollectionTreeItem.ts +++ b/Source/docdb/tree/DocDBCollectionTreeItem.ts @@ -3,115 +3,90 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - ContainerDefinition, - CosmosClient, - PartitionKeyDefinition, - Resource, -} from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; +import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; +import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; +import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; +import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; /** * Represents a DocumentDB collection */ export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor( - parent: DocDBDatabaseTreeItem, - private _container: ContainerDefinition & Resource - ) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( - this - ); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteCollection" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl( - expectedContextValues: (string | RegExp)[] - ): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getDatabaseClient(client).container(this.id); - } + public static contextValue: string = "cosmosDBDocumentCollection"; + public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; + public readonly documentsTreeItem: DocDBDocumentsTreeItem; + public readonly parent: DocDBDatabaseTreeItem; + + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { + super(parent); + this.parent = parent; + this.documentsTreeItem = new DocDBDocumentsTreeItem(this); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._container.id; + } + + public get label(): string { + return this._container.id; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public get link(): string { + return this._container._self; + } + + public get partitionKey(): PartitionKeyDefinition | undefined { + return this._container.partitionKey; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + return [this.documentsTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case DocDBDocumentsTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + return this.documentsTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return (this.parent.getDatabaseClient(client)).container(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItem.ts b/Source/docdb/tree/DocDBDatabaseTreeItem.ts index b51504cc2..ee8c23694 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItem.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItem.ts @@ -3,27 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ContainerDefinition, - CosmosClient, - Database, - Resource, -} from "@azure/cosmos"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItemBase } from "./DocDBDatabaseTreeItemBase"; +import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; + public static contextValue: string = "cosmosDBDocumentDatabase"; + public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = 'Collection'; - public initChild( - container: ContainerDefinition & Resource - ): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } + public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { + return new DocDBCollectionTreeItem(this, container); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts index 15a935e5c..aa7e8d779 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts @@ -3,27 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ContainerDefinition, - ContainerResponse, - CosmosClient, - DatabaseDefinition, - FeedOptions, - QueryIterator, - RequestOptions, - Resource, -} from "@azure/cosmos"; -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; +import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; const minThroughputFixed: number = 400; const minThroughputPartitioned: number = 400; @@ -34,177 +19,143 @@ const throughputStepSize = 100; * This class provides common logic for DocumentDB, Graph, and Table databases * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase< - ContainerDefinition & Resource -> { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor( - parent: DocDBAccountTreeItemBase, - database: DatabaseDefinition & Resource - ) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("database"); - } - - public get id(): string { - return nonNullProp(this._database, "id"); - } - - public get label(): string { - return nonNullProp(this._database, "id"); - } - - public get link(): string { - return nonNullProp(this._database, "_self"); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return client - .database(this._database.id) - .containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteDatabase" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}`, - }); - - const containerDefinition: ContainerDefinition = { - id: containerName, - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey], - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !containerDefinition.partitionKey; - const minThroughput = isFixed - ? minThroughputFixed - : minThroughputPartitioned; - const throughput: number = Number( - await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: "throughputCapacity", - validateInput: (input: string) => - validateThroughput(isFixed, input), - }) - ); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client - .database(this.id) - .containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, "resource")); - } - - protected async getNewPartitionKey( - context: IActionContext - ): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: "Enter the partition key for the collection, or leave blank for fixed size.", - stepName: "partitionKeyForCollection", - validateInput: this.validatePartitionKey, - placeHolder: "e.g. /address/zipCode", - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { - partitionKey = "/" + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } +export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { + public readonly parent: DocDBAccountTreeItemBase; + private readonly _database: DatabaseDefinition & Resource; + + constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { + super(parent); + this._database = database; + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('database'); + } + + public get id(): string { + return nonNullProp(this._database, 'id'); + } + + public get label(): string { + return nonNullProp(this._database, 'id'); + } + + public get link(): string { + return nonNullProp(this._database, '_self'); + } + + public get connectionString(): string { + return this.parent.connectionString.concat(`;Database=${this.id}`); + } + + public get databaseName(): string { + return this._database.id; + } + + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return client.database(this._database.id).containers.readAll(feedOptions); + } + + // Delete the database + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await client.database(this.id).delete(); + } + + // Create a DB collection + public async createChildImpl(context: ICreateChildImplContext): Promise { + const containerName = await context.ui.showInputBox({ + placeHolder: `Enter an id for your ${this.childTypeLabel}`, + validateInput: validateCollectionName, + stepName: `create${this.childTypeLabel}` + }); + + const containerDefinition: ContainerDefinition = { + id: containerName + }; + + const partitionKey = await this.getNewPartitionKey(context); + if (partitionKey) { + containerDefinition.partitionKey = { + paths: [partitionKey] + }; + } + const options: RequestOptions = {}; + + if (!this.parent.isServerless) { + const isFixed: boolean = !(containerDefinition.partitionKey); + const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; + const throughput: number = Number(await context.ui.showInputBox({ + value: minThroughput.toString(), + prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, + stepName: 'throughputCapacity', + validateInput: (input: string) => validateThroughput(isFixed, input) + })); + + if (throughput !== 0) { + options.offerThroughput = throughput; + } + } + + context.showCreatingTreeItem(containerName); + const client = this.root.getCosmosClient(); + const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); + + return this.initChild(nonNullProp(container, 'resource')); + } + + protected async getNewPartitionKey(context: IActionContext): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', + stepName: 'partitionKeyForCollection', + validateInput: this.validatePartitionKey, + placeHolder: 'e.g. /address/zipCode' + }); + + if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { + partitionKey = '/' + partitionKey; + } + + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + return undefined; + } } -function validateThroughput( - isFixed: boolean, - input: string -): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed - ? minThroughputFixed - : minThroughputPartitioned; - const value = Number(input); - if ( - value < minThroughput || - value > maxThroughput || - (value - minThroughput) % throughputStepSize !== 0 - ) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; +function validateThroughput(isFixed: boolean, input: string): string | undefined | null { + if (input === "0") { + return undefined; + } + + try { + const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; + const value = Number(input); + if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { + return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; + } + } catch (err) { + return "Input must be a number"; + } + return undefined; } function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; + if (!name) { + return "Collection name cannot be empty"; + } + if (name.endsWith(" ")) { + return "Collection name cannot end with space"; + } + if (/[/\\?#]/.test(name)) { + return `Collection name cannot contain the characters '\\', '/', '#', '?'`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBDocumentTreeItem.ts b/Source/docdb/tree/DocDBDocumentTreeItem.ts index 408dedfd7..1505572d9 100644 --- a/Source/docdb/tree/DocDBDocumentTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentTreeItem.ts @@ -3,171 +3,131 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - CosmosClient, - Item, - ItemDefinition, - RequestOptions, -} from "@azure/cosmos"; -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { nonNullProp } from "../../utils/nonNull"; -import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; -import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; -import { sanitizeId } from "./DocDBUtils"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; - -const hiddenFields: string[] = [ - "_rid", - "_self", - "_etag", - "_attachments", - "_ts", -]; +import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; +import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { nonNullProp } from '../../utils/nonNull'; +import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; +import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; +import { sanitizeId } from './DocDBUtils'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; + +const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; /** * Represents a Cosmos DB DocumentDB (SQL) document */ -export class DocDBDocumentTreeItem - extends AzExtTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = "cosmosDB.openDocument"; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + "-cosmos-document.json"; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("file"); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteDocument" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent( - _context: IActionContext, - content: string - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error( - `The "_self" and "_etag" fields are required to update a document` - ); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { - accessCondition: { type: "IfMatch", condition: newData._etag }, - }; - const response = await this.getDocumentClient(client).replace( - newData, - options - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { - //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split("/"); - if (fields[0] === "") { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { - //Partition Key exists, but this document doesn't have a value - return ""; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent - .getContainerClient(client) - .item( - nonNullProp(this.document, "id"), - this.getPartitionKeyValue() - ); - } +export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { + public static contextValue: string = "cosmosDBDocument"; + public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; + public readonly parent: DocDBDocumentsTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + private _label: string; + private _document: ItemDefinition; + + constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { + super(parent); + this._document = document; + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + this.commandId = 'cosmosDB.openDocument'; + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); + } + + public get filePath(): string { + return this.label + '-cosmos-document.json'; + } + + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + } + + public get link(): string { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return this.document._self; + } + + get document(): ItemDefinition { + return this._document; + } + + get label(): string { + return this._label; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('file'); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.getDocumentClient(client).delete(); + } + + public async getFileContent(): Promise { + const clonedDoc: {} = { ...this.document }; + for (const field of hiddenFields) { + delete clonedDoc[field]; + } + return JSON.stringify(clonedDoc, null, 2); + } + + public async writeFileContent(_context: IActionContext, content: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const newData = JSON.parse(content); + for (const field of hiddenFields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + newData[field] = this.document[field]; + } + + const client: CosmosClient = this.root.getCosmosClient(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (["_etag"].some((element) => !newData[element])) { + throw new Error(`The "_self" and "_etag" fields are required to update a document`); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; + const response = await this.getDocumentClient(client).replace(newData, options); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this._document = response.resource; + } + } + + private getPartitionKeyValue(): string | undefined | Object { + const partitionKey = this.parent.parent.partitionKey; + if (!partitionKey) { //Fixed collections -> no partitionKeyValue + return undefined; + } + const fields = partitionKey.paths[0].split('/'); + if (fields[0] === '') { + fields.shift(); + } + let value; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + value = value ? value[field] : this.document[field]; + if (!value) { //Partition Key exists, but this document doesn't have a value + return ''; + } + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + } + + private getDocumentClient(client: CosmosClient): Item { + return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); + } } diff --git a/Source/docdb/tree/DocDBDocumentsTreeItem.ts b/Source/docdb/tree/DocDBDocumentsTreeItem.ts index ec05451e0..b8265444d 100644 --- a/Source/docdb/tree/DocDBDocumentsTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentsTreeItem.ts @@ -3,160 +3,127 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - CosmosClient, - FeedOptions, - ItemDefinition, - ItemResponse, - QueryIterator, -} from "@azure/cosmos"; -import { - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; +import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; /** * This class provides logic for DocumentDB collections */ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - let docID = await context.ui.showInputBox({ - prompt: "Enter a document ID or leave blank for a generated ID", - stepName: "createDocument", - }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = await this.promptForPartitionKey(context, body); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = - await this.getContainerClient( - this.root.getCosmosClient() - ).items.create(body); - return nonNullProp(item, "resource"); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = - this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === "/") { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split("/"); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey( - context: IActionContext, - body: ItemDefinition - ): Promise { - const partitionKey: string | undefined = - this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: "valueforParititionKey", - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign( - body, - this.createPartitionPathObject(partitionKey, partitionKeyValue) - ); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject( - partitionKey: string, - partitionKeyValue: string - ): Object { - //remove leading slash - if (partitionKey[0] === "/") { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split("/"); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } + public static contextValue: string = "cosmosDBDocumentsGroup"; + public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; + public readonly childTypeLabel: string = "Documents"; + public readonly parent: DocDBCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public get id(): string { + return "$Documents"; + } + + public get label(): string { + return "Documents"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return this.getContainerClient(client).items.readAll(feedOptions); + } + + public initChild(document: ItemDefinition): DocDBDocumentTreeItem { + return new DocDBDocumentTreeItem(this, document); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); + + docID = docID.trim(); + let body: ItemDefinition = { id: docID }; + body = (await this.promptForPartitionKey(context, body)); + context.showCreatingTreeItem(docID); + const item: ItemDefinition = await this.createDocument(body); + + return this.initChild(item); + } + + public async createDocument(body: ItemDefinition): Promise { + const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); + return nonNullProp(item, 'resource'); + } + + public documentHasPartitionKey(doc: Object): boolean { + let interim = doc; + let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (!partitionKey) { + return true; + } + if (partitionKey[0] === '/') { + partitionKey = partitionKey.slice(1); + } + const partitionKeyPath = partitionKey.split('/'); + + for (const prop of partitionKeyPath) { + // eslint-disable-next-line no-prototype-builtins + if (interim.hasOwnProperty(prop)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[prop]; + } else { + return false; + } + } + return true; + } + + public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { + const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (partitionKey) { + const partitionKeyValue: string = await context.ui.showInputBox({ + prompt: `Enter a value for the partition key ("${partitionKey}")`, + stepName: 'valueforParititionKey' + }); + // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. + // We need to present the partitionKey value as part of the document contents + Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); + } + return body; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + // Create a nested Object given the partition key path and value + private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { + //remove leading slash + if (partitionKey[0] === '/') { + partitionKey = partitionKey.slice(1); + } + const keyPath = partitionKey.split('/'); + const PartitionPath: Object = {}; + let interim: Object = PartitionPath; + let i: number; + for (i = 0; i < keyPath.length - 1; i++) { + interim[keyPath[i]] = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[keyPath[i]]; + } + interim[keyPath[i]] = partitionKeyValue; + return PartitionPath; + } } diff --git a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts index 20ced0d3e..899eccd27 100644 --- a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts @@ -3,100 +3,74 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; +import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; +import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; /** * Represents a Cosmos DB DocumentDB (SQL) stored procedure */ -export class DocDBStoredProcedureTreeItem - extends AzExtTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = - DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); +export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { + public static contextValue: string = "cosmosDBStoredProcedure"; + public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; + public readonly cTime: number = Date.now(); + public readonly parent: DocDBStoredProceduresTreeItem; + public mTime: number = Date.now(); - constructor( - parent: DocDBStoredProceduresTreeItem, - public procedure: StoredProcedureDefinition & Resource - ) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = "cosmosDB.openStoredProcedure"; - } + constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { + super(parent); + ext.fileSystem.fireChangedEvent(this); + this.commandId = 'cosmosDB.openStoredProcedure'; + } - public get root(): IDocDBTreeRoot { - return this.parent.root; - } + public get root(): IDocDBTreeRoot { + return this.parent.root; + } - public get filePath(): string { - return this.label + "-cosmos-stored-procedure.js"; - } + public get filePath(): string { + return this.label + '-cosmos-stored-procedure.js'; + } - public get id(): string { - return this.procedure.id; - } + public get id(): string { + return this.procedure.id; + } - public get label(): string { - return this.procedure.id; - } + public get label(): string { + return this.procedure.id; + } - public get link(): string { - return this.procedure._self; - } + public get link(): string { + return this.procedure._self; + } - public async getFileContent(): Promise { - return typeof this.procedure.body === "string" - ? this.procedure.body - : ""; - } + public async getFileContent(): Promise { + return typeof this.procedure.body === 'string' ? this.procedure.body : ''; - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } + } - public async writeFileContent( - _context: IActionContext, - content: string - ): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent - .getContainerClient(client) - .scripts.storedProcedure(this.id) - .replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, "resource"); - } + public async refreshImpl(): Promise { + ext.fileSystem.fireChangedEvent(this); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("server-process"); - } + public async writeFileContent(_context: IActionContext, content: string): Promise { + const client = this.root.getCosmosClient(); + const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); + this.procedure = nonNullProp(replace, 'resource'); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteStoredProcedure" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.parent - .getContainerClient(client) - .scripts.storedProcedure(this.id) - .delete(); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('server-process'); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); + } } diff --git a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts index a869e8a99..4c3ddfd1a 100644 --- a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts @@ -3,141 +3,95 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - CosmosClient, - FeedOptions, - QueryIterator, - Resource, - StoredProcedureDefinition, -} from "@azure/cosmos"; -import { - AzExtTreeItem, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; +import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; +import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; import * as vscode from "vscode"; -import { defaultStoredProcedure } from "../../constants"; -import { GraphCollectionTreeItem } from "../../graph/tree/GraphCollectionTreeItem"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { defaultStoredProcedure } from '../../constants'; +import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; +import { localize } from '../../utils/localize'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; /** * This class represents the DocumentDB "Stored Procedures" node in the tree */ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = - DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild( - resource: StoredProcedureDefinition & Resource - ): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("server-process"); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = - await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = ( - await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: "createStoredProcedure", - validateInput: (name: string) => - this.validateStoredProcedureName( - name, - currStoredProcedureNames - ), - }) - ).trim(); - const body: StoredProcedureDefinition = { - id: spID, - body: defaultStoredProcedure, - }; - context.showCreatingTreeItem(spID); - const sproc = - await this.getContainerClient( - client - ).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, "resource")); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll( - feedOptions - ); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName( - name: string, - currStoredProcedureNames: string[] - ): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize( - "nameLength", - "Name has to be between 1 and 255 chars long" - ); - } - - if (/[/\\?#&]/.test(name)) { - return localize( - "illegalChars", - "Name contains illegal chars: /, \\, ?, #, &" - ); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize( - "nameExists", - 'Stored Procedure "{0}" already exists.', - name - ); - } - - return undefined; - } + + public static contextValue: string = "cosmosDBStoredProceduresGroup"; + public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; + public readonly childTypeLabel: string = "Stored Procedure"; + public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { + return new DocDBStoredProcedureTreeItem(this, resource); + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('server-process'); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + const client = this.root.getCosmosClient(); + const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); + const currStoredProcedureNames: string[] = []; + for (const sp of currStoredProcedureList) { + currStoredProcedureNames.push(nonNullProp(sp, "id")); + } + const spID = (await context.ui.showInputBox({ + prompt: "Enter a unique stored procedure ID", + stepName: 'createStoredProcedure', + validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) + })).trim(); + const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; + context.showCreatingTreeItem(spID); + const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); + + return this.initChild(nonNullProp(sproc, 'resource')); + } + + public get id(): string { + return "$StoredProcedures"; + } + + public get label(): string { + return "Stored Procedures"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { + if (name.length < 1 || name.length > 255) { + return localize("nameLength", "Name has to be between 1 and 255 chars long"); + } + + if (/[/\\?#&]/.test(name)) { + return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); + } + if (name[name.length - 1] === " ") { + return localize("endsWithSpace", "Name cannot end with a space."); + } + if (currStoredProcedureNames.includes(name)) { + return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); + } + + return undefined; + } } diff --git a/Source/docdb/tree/DocDBTreeItemBase.ts b/Source/docdb/tree/DocDBTreeItemBase.ts index 0774fbcdc..4424603ae 100644 --- a/Source/docdb/tree/DocDBTreeItemBase.ts +++ b/Source/docdb/tree/DocDBTreeItemBase.ts @@ -3,64 +3,53 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, FeedOptions, QueryIterator } from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, -} from "@microsoft/vscode-azext-utils"; -import { getBatchSizeSetting } from "../../utils/workspacUtils"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; +import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; +import { getBatchSizeSetting } from '../../utils/workspacUtils'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; /** * This class provides common iteration logic for DocumentDB accounts, databases, and collections */ export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; + public abstract readonly label: string; + public abstract readonly contextValue: string; + public abstract readonly childTypeLabel: string; - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); + private _hasMoreChildren: boolean = true; + private _iterator: QueryIterator | undefined; + private _batchSize: number = getBatchSizeSetting(); - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } - public root: IDocDBTreeRoot; + public root: IDocDBTreeRoot; - public abstract initChild(resource: T): AzExtTreeItem; + public abstract initChild(resource: T): AzExtTreeItem; - public abstract getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator; + public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + } - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { - maxItemCount: this._batchSize, - }); - } + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (clearCache || this._iterator === undefined) { + this._hasMoreChildren = true; + const client = this.root.getCosmosClient(); + this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); + } - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()) - .resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); + const resourceArray: T[] = []; + const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; + if (resourceFeed) { + resourceArray.push(...resourceFeed); + } + this._hasMoreChildren = this._iterator.hasMoreResults(); - this._batchSize *= 2; + this._batchSize *= 2; - return resourceArray.map((resource: T) => this.initChild(resource)); - } + return resourceArray.map((resource: T) => this.initChild(resource)); + } } diff --git a/Source/docdb/tree/DocDBUtils.ts b/Source/docdb/tree/DocDBUtils.ts index 1a0630d53..3d45cf950 100644 --- a/Source/docdb/tree/DocDBUtils.ts +++ b/Source/docdb/tree/DocDBUtils.ts @@ -8,5 +8,5 @@ * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding */ export function sanitizeId(id: string): string { - return id.replace(/\+/g, " "); + return id.replace(/\+/g, ' '); } diff --git a/Source/docdb/tree/IDocDBTreeRoot.ts b/Source/docdb/tree/IDocDBTreeRoot.ts index 6827564c2..9179eb454 100644 --- a/Source/docdb/tree/IDocDBTreeRoot.ts +++ b/Source/docdb/tree/IDocDBTreeRoot.ts @@ -1,3 +1,4 @@ + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -6,8 +7,8 @@ import { CosmosClient } from "@azure/cosmos"; export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; + endpoint: string; + masterKey: string; + isEmulator: boolean | undefined; + getCosmosClient(): CosmosClient; } diff --git a/Source/extension.ts b/Source/extension.ts index c712fbc4c..e68744157 100644 --- a/Source/extension.ts +++ b/Source/extension.ts @@ -3,409 +3,213 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -"use strict"; - -import { registerAzureUtilsExtensionVariables } from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - AzureExtensionApi, - IActionContext, - ITreeItemPickerContext, - apiUtils, - callWithTelemetryAndErrorHandling, - createApiProvider, - createAzExtOutputChannel, - registerCommandWithTreeNodeUnwrapping, - registerErrorHandler, - registerEvent, - registerReportIssueCommand, - registerUIExtensionVariables, -} from "@microsoft/vscode-azext-utils"; -import { AzExtResourceType } from "@microsoft/vscode-azureresources-api"; -import { platform } from "os"; -import * as vscode from "vscode"; -import { DatabasesFileSystem } from "./DatabasesFileSystem"; -import { findTreeItem } from "./commands/api/findTreeItem"; -import { pickTreeItem } from "./commands/api/pickTreeItem"; -import { revealTreeItem } from "./commands/api/revealTreeItem"; -import { deleteDatabaseAccount } from "./commands/deleteDatabaseAccount/deleteDatabaseAccount"; -import { importDocuments } from "./commands/importDocuments"; -import { - cosmosGremlinFilter, - cosmosMongoFilter, - cosmosTableFilter, - doubleClickDebounceDelay, - sqlFilter, -} from "./constants"; -import { registerDocDBCommands } from "./docdb/registerDocDBCommands"; -import { DocDBAccountTreeItem } from "./docdb/tree/DocDBAccountTreeItem"; -import { DocDBAccountTreeItemBase } from "./docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBCollectionTreeItem } from "./docdb/tree/DocDBCollectionTreeItem"; -import { DocDBDocumentTreeItem } from "./docdb/tree/DocDBDocumentTreeItem"; -import { ext } from "./extensionVariables"; -import { getResourceGroupsApi } from "./getExtensionApi"; -import { registerGraphCommands } from "./graph/registerGraphCommands"; -import { GraphAccountTreeItem } from "./graph/tree/GraphAccountTreeItem"; -import { registerMongoCommands } from "./mongo/registerMongoCommands"; -import { setConnectedNode } from "./mongo/setConnectedNode"; -import { MongoAccountTreeItem } from "./mongo/tree/MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./mongo/tree/MongoCollectionTreeItem"; -import { MongoDocumentTreeItem } from "./mongo/tree/MongoDocumentTreeItem"; -import { registerPostgresCommands } from "./postgres/commands/registerPostgresCommands"; -import { DatabaseResolver } from "./resolver/AppResolver"; -import { DatabaseWorkspaceProvider } from "./resolver/DatabaseWorkspaceProvider"; -import { TableAccountTreeItem } from "./table/tree/TableAccountTreeItem"; -import { AttachedAccountSuffix } from "./tree/AttachedAccountsTreeItem"; -import { SubscriptionTreeItem } from "./tree/SubscriptionTreeItem"; -import { localize } from "./utils/localize"; - -const cosmosDBTopLevelContextValues: string[] = [ - GraphAccountTreeItem.contextValue, - DocDBAccountTreeItem.contextValue, - TableAccountTreeItem.contextValue, - MongoAccountTreeItem.contextValue, -]; - -export async function activateInternal( - context: vscode.ExtensionContext, - perfStats: { loadStartTime: number; loadEndTime: number }, - ignoreBundle?: boolean -): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling( - "cosmosDB.activate", - async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = "true"; - activateContext.telemetry.measurements.mainFileLoad = - (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver( - AzExtResourceType.AzureCosmosDb, - new DatabaseResolver() - ); - ext.rgApi.registerApplicationResourceResolver( - AzExtResourceType.PostgresqlServersStandard, - new DatabaseResolver() - ); - ext.rgApi.registerApplicationResourceResolver( - AzExtResourceType.PostgresqlServersFlexible, - new DatabaseResolver() - ); - - const workspaceRootTreeItem = ( - ext.rgApi.workspaceResourceTree as unknown as { - _rootTreeItem: AzExtParentTreeItem; - } - )._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider( - workspaceRootTreeItem - ); - ext.rgApi.registerWorkspaceResourceProvider( - "AttachedDatabaseAccount", - databaseWorkspaceProvider - ); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push( - vscode.workspace.registerFileSystemProvider( - DatabasesFileSystem.scheme, - ext.fileSystem - ) - ); - - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.selectSubscriptions", - () => - vscode.commands.executeCommand( - "azure-account.selectSubscriptions" - ) - ); - - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.createServer", - createServer - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteAccount", - deleteAccount - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.attachDatabaseAccount", - async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount( - actionContext - ); - await ext.rgApi.workspaceResourceTree.refresh( - actionContext, - ext.attachedAccountsNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.attachEmulator", - async (actionContext: IActionContext) => { - if (platform() !== "win32") { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error( - localize( - "emulatorNotSupported", - "The Cosmos DB emulator is only supported on Windows." - ) - ); - } - - await ext.attachedAccountsNode.attachEmulator( - actionContext - ); - await ext.rgApi.workspaceResourceTree.refresh( - actionContext, - ext.attachedAccountsNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.refresh", - async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh( - actionContext, - node - ); - } - } - ); - - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.detachDatabaseAccount", - async ( - actionContext: IActionContext & ITreeItemPickerContext, - node?: AzExtTreeItem - ) => { - const children = - await ext.attachedAccountsNode.loadAllChildren( - actionContext - ); - if ( - children[0].contextValue === - "cosmosDBAttachDatabaseAccount" - ) { - const message = localize( - "noAttachedAccounts", - "There are no Attached Accounts." - ); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = - await ext.rgApi.workspaceResourceTree.showTreeItemPicker( - cosmosDBTopLevelContextValues.map( - (val: string) => - (val += AttachedAccountSuffix) - ), - actionContext - ); - } - if (node instanceof MongoAccountTreeItem) { - if ( - ext.connectedMongoDB && - node.fullId === - ext.connectedMongoDB.parent.fullId - ) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh( - actionContext, - ext.attachedAccountsNode - ); - } - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.importDocument", - async ( - actionContext: IActionContext, - selectedNode: - | vscode.Uri - | MongoCollectionTreeItem - | DocDBCollectionTreeItem, - uris: vscode.Uri[] - ) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments( - actionContext, - uris || [selectedNode], - undefined - ); - } else { - await importDocuments( - actionContext, - undefined, - selectedNode - ); - } - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.copyConnectionString", - cosmosDBCopyConnectionString - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openDocument", - async ( - actionContext: IActionContext, - node?: MongoDocumentTreeItem | DocDBDocumentTreeItem - ) => { - if (!node) { - node = await ext.rgApi.pickAppResource< - MongoDocumentTreeItem | DocDBDocumentTreeItem - >(actionContext, { - filter: [cosmosMongoFilter, sqlFilter], - expectedChildContextValue: [ - MongoDocumentTreeItem.contextValue, - DocDBDocumentTreeItem.contextValue, - ], - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.update", - async (_actionContext: IActionContext, uri: vscode.Uri) => - await ext.fileSystem.updateWithoutPrompt(uri) - ); - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.loadMore", - async (actionContext: IActionContext, node: AzExtTreeItem) => - await ext.rgApi.appResourceTree.loadMore( - node, - actionContext - ) - ); - registerEvent( - "cosmosDB.onDidChangeConfiguration", - vscode.workspace.onDidChangeConfiguration, - async ( - actionContext: IActionContext, - event: vscode.ConfigurationChangeEvent - ) => { - actionContext.telemetry.properties.isActivationEvent = - "true"; - actionContext.errorHandling.suppressDisplay = true; - if ( - event.affectsConfiguration( - ext.settingsKeys.documentLabelFields - ) - ) { - await vscode.commands.executeCommand( - "azureDatabases.refresh" - ); - } - } - ); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler( - (c) => (c.errorHandling.suppressReportIssue = true) - ); - registerReportIssueCommand("azureDatabases.reportIssue"); - } - ); - - return createApiProvider([ - { - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: "1.2.0", - }, - ]); +'use strict'; + +import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; +import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; +import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; +import { platform } from 'os'; +import * as vscode from 'vscode'; +import { DatabasesFileSystem } from './DatabasesFileSystem'; +import { findTreeItem } from './commands/api/findTreeItem'; +import { pickTreeItem } from './commands/api/pickTreeItem'; +import { revealTreeItem } from './commands/api/revealTreeItem'; +import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; +import { importDocuments } from './commands/importDocuments'; +import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; +import { registerDocDBCommands } from './docdb/registerDocDBCommands'; +import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; +import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; +import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; +import { ext } from './extensionVariables'; +import { getResourceGroupsApi } from './getExtensionApi'; +import { registerGraphCommands } from './graph/registerGraphCommands'; +import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; +import { registerMongoCommands } from './mongo/registerMongoCommands'; +import { setConnectedNode } from './mongo/setConnectedNode'; +import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; +import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; +import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; +import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; +import { DatabaseResolver } from './resolver/AppResolver'; +import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; +import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; +import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; +import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; +import { localize } from './utils/localize'; + +const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; + +export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { + ext.context = context; + ext.ignoreBundle = ignoreBundle; + + ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); + context.subscriptions.push(ext.outputChannel); + registerUIExtensionVariables(ext); + registerAzureUtilsExtensionVariables(ext); + + await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { + activateContext.telemetry.properties.isActivationEvent = 'true'; + activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; + + ext.secretStorage = context.secrets; + + ext.rgApi = await getResourceGroupsApi(); + ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); + ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); + ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); + + const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; + const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); + ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); + + ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); + + registerDocDBCommands(); + registerGraphCommands(); + registerPostgresCommands(); + registerMongoCommands(); + + context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); + + registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); + + registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); + registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { + await ext.attachedAccountsNode.attachNewAccount(actionContext); + await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { + if (platform() !== 'win32') { + actionContext.errorHandling.suppressReportIssue = true; + throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); + } + + await ext.attachedAccountsNode.attachEmulator(actionContext); + await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); + }); + registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { + if (node) { + await node.refresh(actionContext); + } else { + await ext.rgApi.appResourceTree.refresh(actionContext, node); + } + }); + + registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { + const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); + if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { + const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); + void vscode.window.showInformationMessage(message); + } else { + if (!node) { + node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); + } + if (node instanceof MongoAccountTreeItem) { + if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { + setConnectedNode(undefined); + await node.refresh(actionContext); + } + } + await ext.attachedAccountsNode.detach(node); + await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); + } + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { + if (selectedNode instanceof vscode.Uri) { + await importDocuments(actionContext, uris || [selectedNode], undefined); + } else { + await importDocuments(actionContext, undefined, selectedNode); + } + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { + if (!node) { + node = await ext.rgApi.pickAppResource(actionContext, { + filter: [ + cosmosMongoFilter, + sqlFilter + ], + expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] + }); + } + + // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 + ext.fileSystem.fireChangedEvent(node); + await ext.fileSystem.showTextDocument(node); + }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); + registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); + registerEvent( + 'cosmosDB.onDidChangeConfiguration', + vscode.workspace.onDidChangeConfiguration, + async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { + actionContext.telemetry.properties.isActivationEvent = "true"; + actionContext.errorHandling.suppressDisplay = true; + if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { + await vscode.commands.executeCommand("azureDatabases.refresh"); + } + }); + + // Suppress "Report an Issue" button for all errors in favor of the command + registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); + registerReportIssueCommand('azureDatabases.reportIssue'); + }); + + return createApiProvider([{ + findTreeItem, + pickTreeItem, + revealTreeItem, + apiVersion: '1.2.0' + }]); } // this method is called when your extension is deactivated export function deactivateInternal(): void { - // NOOP + // NOOP } -export async function createServer( - context: IActionContext, - node?: SubscriptionTreeItem -): Promise { - if (!node) { - node = - await ext.rgApi.appResourceTree.showTreeItemPicker( - SubscriptionTreeItem.contextValue, - context - ); - } +export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { + if (!node) { + node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); + } - await SubscriptionTreeItem.createChild(context, node); + await SubscriptionTreeItem.createChild(context, node); } -export async function deleteAccount( - context: IActionContext, - node?: AzExtTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter, - ], - }); - } - - await deleteDatabaseAccount(context, node, false); +export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter + ] + }); + } + + await deleteDatabaseAccount(context, node, false) } -export async function cosmosDBCopyConnectionString( - context: IActionContext, - node?: MongoAccountTreeItem | DocDBAccountTreeItemBase -): Promise { - const message = "The connection string has been copied to the clipboard"; - if (!node) { - node = await ext.rgApi.pickAppResource< - MongoAccountTreeItem | DocDBAccountTreeItemBase - >(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter, - ], - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); +export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { + const message = 'The connection string has been copied to the clipboard'; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter + ] + }); + } + + await vscode.env.clipboard.writeText(node.connectionString); + void vscode.window.showInformationMessage(message); } diff --git a/Source/extensionVariables.ts b/Source/extensionVariables.ts index 3af61432c..4a3fc2650 100644 --- a/Source/extensionVariables.ts +++ b/Source/extensionVariables.ts @@ -3,11 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeDataProvider, - AzExtTreeItem, - IAzExtOutputChannel, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { ExtensionContext, SecretStorage, TreeView } from "vscode"; import { DatabasesFileSystem } from "./DatabasesFileSystem"; @@ -23,34 +19,33 @@ import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWit * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts */ export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = "azureDatabases"; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; + export let connectedMongoDB: MongoDatabaseTreeItem | undefined; + export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; + export let context: ExtensionContext; + export let outputChannel: IAzExtOutputChannel; + export let tree: AzExtTreeDataProvider; + export let treeView: TreeView; + export let attachedAccountsNode: AttachedAccountsTreeItem; + export let ignoreBundle: boolean | undefined; + export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; + export let secretStorage: SecretStorage; + export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; + export const prefix: string = 'azureDatabases'; + export let fileSystem: DatabasesFileSystem; + export let mongoCodeLensProvider: MongoCodeLensProvider; + export let mongoLanguageClient: MongoDBLanguageClient; + export let rgApi: AzureHostExtensionApi; - export namespace settingsKeys { - export const mongoShellPath = "mongo.shell.path"; - export const mongoShellArgs = "mongo.shell.args"; - export const documentLabelFields = "cosmosDB.documentLabelFields"; - export const enableEndpointDiscovery = - "cosmosDB.enableEndpointDiscovery"; - export const mongoShellTimeout = "mongo.shell.timeout"; - export const batchSize = "azureDatabases.batchSize"; + export namespace settingsKeys { + export const mongoShellPath = 'mongo.shell.path'; + export const mongoShellArgs = 'mongo.shell.args'; + export const documentLabelFields = 'cosmosDB.documentLabelFields'; + export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; + export const mongoShellTimeout = 'mongo.shell.timeout'; + export const batchSize = 'azureDatabases.batchSize'; - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } + export namespace vsCode { + export const proxyStrictSSL = "http.proxyStrictSSL"; + } + } } diff --git a/Source/getExtensionApi.ts b/Source/getExtensionApi.ts index 63efdb7e5..bfd553e74 100644 --- a/Source/getExtensionApi.ts +++ b/Source/getExtensionApi.ts @@ -8,35 +8,24 @@ import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { Extension, extensions } from "vscode"; import { localize } from "./utils/localize"; -export async function getApiExport( - extensionId: string -): Promise { - const extension: Extension | undefined = - extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } +export async function getApiExport(extensionId: string): Promise { + const extension: Extension | undefined = extensions.getExtension(extensionId); + if (extension) { + if (!extension.isActive) { + await extension.activate(); + } - return extension.exports; - } + return extension.exports; + } - return undefined; + return undefined; } export async function getResourceGroupsApi(): Promise { - const rgApiProvider = - await getApiExport( - "ms-azuretools.vscode-azureresourcegroups" - ); - if (rgApiProvider) { - return rgApiProvider.getApi("0.0.1"); - } else { - throw new Error( - localize( - "noResourceGroupExt", - "Could not find the Azure Resource Groups extension" - ) - ); - } + const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); + if (rgApiProvider) { + return rgApiProvider.getApi('0.0.1'); + } else { + throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); + } } diff --git a/Source/graph/gremlinEndpoints.ts b/Source/graph/gremlinEndpoints.ts index 0bbeae16f..1ef6b283d 100644 --- a/Source/graph/gremlinEndpoints.ts +++ b/Source/graph/gremlinEndpoints.ts @@ -3,50 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { nonNullValue } from "../utils/nonNull"; -import { IGremlinEndpoint } from "../vscode-cosmosdbgraph.api"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { nonNullValue } from '../utils/nonNull'; +import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; -export async function tryGetGremlinEndpointFromAzure( - client: CosmosDBManagementClient, - resourceGroup: string, - account: string -): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; +export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { + // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk + const response = await client.databaseAccounts.get(resourceGroup, account); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const endpointUri = response.documentEndpoint; + // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint + return endpointUri ? parseEndpointUrl(endpointUri) : undefined; } -export function getPossibleGremlinEndpoints( - documentEndpoint: string -): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ +export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { + // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - const documentSuffix = ".documents.azure.com"; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace( - documentSuffix, - ".graphs.azure.com" - ); + const documentSuffix = '.documents.azure.com'; + if (documentEndpoint.indexOf(documentSuffix) >= 0) { + // Pre-GA style (Dec 2017) + const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace( - documentSuffix, - ".gremlin.cosmosdb.azure.com" - ); + // Post-GA style (Dec 2017) + const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); - return [ - parseEndpointUrl(postGAEndpoint), - parseEndpointUrl(preGAEndpoint), - ]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } + return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; + } else { + console.warn(`Unexpected document URL format: ${documentEndpoint}`); + return [parseEndpointUrl(documentEndpoint)]; + } } /** @@ -54,12 +39,9 @@ export function getPossibleGremlinEndpoints( * @param url An account URL such as 'https://.documents.azure.com:443/' */ function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue( - url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), - "urlMatch" - ); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; + const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); + console.assert(!!protocol && !!host, "Unexpected endpoint format"); + const port = parseInt(portString || "443", 10); + console.assert(port > 0, "Unexpected port"); + return { host, port, ssl: protocol.toLowerCase() === "https" }; } diff --git a/Source/graph/registerGraphCommands.ts b/Source/graph/registerGraphCommands.ts index 21e05d9a5..1746c638b 100644 --- a/Source/graph/registerGraphCommands.ts +++ b/Source/graph/registerGraphCommands.ts @@ -3,97 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - IActionContext, - ITreeItemPickerContext, - registerCommandWithTreeNodeUnwrapping, -} from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from "../constants"; -import { ext } from "../extensionVariables"; +import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; +import { ext } from '../extensionVariables'; import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; import { GraphTreeItem } from "./tree/GraphTreeItem"; export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createGraphDatabase", - createGraphDatabase - ); - registerCommandWithTreeNodeUnwrapping("cosmosDB.createGraph", createGraph); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteGraphDatabase", - async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph( - context, - GraphDatabaseTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteGraph", - async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph( - context, - GraphCollectionTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openGraphExplorer", - async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph( - context, - GraphTreeItem.contextValue - ); - } - await node.showExplorer(context); - }, - doubleClickDebounceDelay - ); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph(context, GraphCollectionTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { + if (!node) { + node = await pickGraph(context, GraphTreeItem.contextValue); + } + await node.showExplorer(context); + }, doubleClickDebounceDelay); } -export async function createGraphDatabase( - context: IActionContext, - node?: GraphAccountTreeItem -): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); +export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { + if (!node) { + node = await pickGraph(context); + } + await node.createChild(context); } -export async function createGraph( - context: IActionContext, - node?: GraphDatabaseTreeItem -): Promise { - if (!node) { - node = await pickGraph( - context, - GraphDatabaseTreeItem.contextValue - ); - } - await node.createChild(context); +export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { + if (!node) { + node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); + } + await node.createChild(context); } -async function pickGraph( - context: IActionContext, - expectedContextValue?: string | RegExp | (string | RegExp)[] -): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [cosmosGremlinFilter], - expectedChildContextValue: expectedContextValue, - }); +async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosGremlinFilter + ], + expectedChildContextValue: expectedContextValue + }); } diff --git a/Source/graph/tree/GraphAccountTreeItem.ts b/Source/graph/tree/GraphAccountTreeItem.ts index 8025e4f8e..7e1f561fa 100644 --- a/Source/graph/tree/GraphAccountTreeItem.ts +++ b/Source/graph/tree/GraphAccountTreeItem.ts @@ -3,62 +3,43 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { DatabaseDefinition, Resource } from "@azure/cosmos"; -import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; -import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; -import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; -import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./GraphTreeItem"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { DatabaseDefinition, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; +import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; +import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; +import { GraphTreeItem } from './GraphTreeItem'; export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBGraphAccount"; + public contextValue: string = GraphAccountTreeItem.contextValue; - constructor( - parent: AzExtParentTreeItem, - id: string, - label: string, - documentEndpoint: string, - private _gremlinEndpoint: IGremlinEndpoint | undefined, - masterKey: string, - isEmulator: boolean | undefined, - readonly databaseAccount?: DatabaseAccountGetResults - ) { - super( - parent, - id, - label, - documentEndpoint, - masterKey, - isEmulator, - databaseAccount - ); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } + constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { + super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); + this.valuesToMask.push(documentEndpoint); + if (_gremlinEndpoint) { + this.valuesToMask.push(_gremlinEndpoint.host); + } + } - public initChild( - database: DatabaseDefinition & Resource - ): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } + public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { + return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case GraphDatabaseTreeItem.contextValue: + case GraphCollectionTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case GraphTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/graph/tree/GraphCollectionTreeItem.ts b/Source/graph/tree/GraphCollectionTreeItem.ts index efc25ae4c..63709d977 100644 --- a/Source/graph/tree/GraphCollectionTreeItem.ts +++ b/Source/graph/tree/GraphCollectionTreeItem.ts @@ -3,108 +3,85 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - ContainerDefinition, - CosmosClient, - Resource, -} from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; -import { IDocDBTreeRoot } from "../../docdb/tree/IDocDBTreeRoot"; -import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./GraphTreeItem"; +import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; +import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; +import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; +import { GraphTreeItem } from './GraphTreeItem'; export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor( - parent: GraphDatabaseTreeItem, - collection: ContainerDefinition & Resource - ) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( - this - ); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteGraphCollection" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl( - expectedContextValues: (string | RegExp)[] - ): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getDatabaseClient(client).container(this.id); - } + public static contextValue: string = "cosmosDBGraph"; + public readonly contextValue: string = GraphCollectionTreeItem.contextValue; + public readonly parent: GraphDatabaseTreeItem; + + private readonly _graphTreeItem: GraphTreeItem; + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + private readonly _collection: ContainerDefinition & Resource; + + constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { + super(parent); + this._collection = collection; + this._graphTreeItem = new GraphTreeItem(this, this._collection); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return this._collection.id; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + return [this._graphTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case GraphTreeItem.contextValue: + return this._graphTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return (this.parent.getDatabaseClient(client)).container(this.id); + + } } diff --git a/Source/graph/tree/GraphDatabaseTreeItem.ts b/Source/graph/tree/GraphDatabaseTreeItem.ts index 4fc7a9655..1c5332700 100644 --- a/Source/graph/tree/GraphDatabaseTreeItem.ts +++ b/Source/graph/tree/GraphDatabaseTreeItem.ts @@ -3,76 +3,63 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ContainerDefinition, - CosmosClient, - Database, - DatabaseDefinition, - Resource, -} from "@azure/cosmos"; -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; -import { getPossibleGremlinEndpoints } from "../gremlinEndpoints"; -import { GraphAccountTreeItem } from "./GraphAccountTreeItem"; -import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; +import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; +import { GraphAccountTreeItem } from './GraphAccountTreeItem'; +import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Graph"; + public static contextValue: string = "cosmosDBGraphDatabase"; + public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = 'Graph'; - constructor( - parent: GraphAccountTreeItem, - private _gremlinEndpoint: IGremlinEndpoint | undefined, - database: DatabaseDefinition & Resource - ) { - super(parent, database); - } + constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { + super(parent, database); + } - public initChild( - collection: ContainerDefinition & Resource - ): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } + public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { + return new GraphCollectionTreeItem(this, collection); + } - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } + // Gremlin endpoint, if definitely known + get gremlinEndpoint(): IGremlinEndpoint | undefined { + return this._gremlinEndpoint; + } - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } + get possibleGremlinEndpoints(): IGremlinEndpoint[] { + return getPossibleGremlinEndpoints(this.root.endpoint); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); - protected override async getNewPartitionKey( - context: IActionContext - ): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: "Enter the partition key for the collection, or leave blank for fixed size.", - stepName: "partitionKeyForCollection", - validateInput: this.validatePartitionKey, - placeHolder: "e.g. /address", - }); + } - if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { - partitionKey = "/" + partitionKey; - } + protected override async getNewPartitionKey(context: IActionContext): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', + stepName: 'partitionKeyForCollection', + validateInput: this.validatePartitionKey, + placeHolder: 'e.g. /address' + }); - return partitionKey; - } + if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { + partitionKey = '/' + partitionKey; + } - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + if (/.+\//.test(key)) { + return "Cannot be a nested path"; + } + return undefined; + } } diff --git a/Source/graph/tree/GraphTreeItem.ts b/Source/graph/tree/GraphTreeItem.ts index d98da8b6b..800fded5a 100644 --- a/Source/graph/tree/GraphTreeItem.ts +++ b/Source/graph/tree/GraphTreeItem.ts @@ -3,65 +3,54 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, Resource } from "@azure/cosmos"; -import { - AzExtTreeItem, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { localize } from "../../utils/localize"; -import { openUrl } from "../../utils/openUrl"; -import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { ContainerDefinition, Resource } from '@azure/cosmos'; +import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { localize } from '../../utils/localize'; +import { openUrl } from '../../utils/openUrl'; +import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -const alternativeGraphVisualizationToolsDocLink = - "https://aka.ms/cosmosdb-graph-alternative-tools"; +const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor( - parent: GraphCollectionTreeItem, - collection: ContainerDefinition & Resource - ) { - super(parent); - this.commandId = "cosmosDB.openGraphExplorer"; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize( - "mustInstallGraph", - "Cosmos DB Graph extension has been retired." - ); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } + public static contextValue: string = "cosmosDBGraphGraph"; + public readonly contextValue: string = GraphTreeItem.contextValue; + public readonly parent: GraphCollectionTreeItem; + public suppressMaskLabel = true; + + private readonly _collection: ContainerDefinition & Resource; + + constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { + super(parent); + this.commandId = 'cosmosDB.openGraphExplorer'; + this._collection = collection; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return "Graph"; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public async showExplorer(_context: IActionContext): Promise { + const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); + const alternativeToolsOption = "Alternative Tools"; + const result = await vscode.window.showErrorMessage( + message, + alternativeToolsOption + ); + if (result === alternativeToolsOption) { + await openUrl(alternativeGraphVisualizationToolsDocLink); + } + } } diff --git a/Source/mongo/MongoCommand.ts b/Source/mongo/MongoCommand.ts index ea9466b45..79c33731f 100644 --- a/Source/mongo/MongoCommand.ts +++ b/Source/mongo/MongoCommand.ts @@ -3,22 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RecognitionException } from "antlr4ts"; -import * as vscode from "vscode"; +import { RecognitionException } from 'antlr4ts'; +import * as vscode from 'vscode'; export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; + range: vscode.Range; + text: string; + collection?: string; + name?: string; + arguments?: string[]; + argumentObjects?: Object[]; + errors?: ErrorDescription[]; + chained?: boolean; } export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; + range: vscode.Range; + message: string; + exception?: RecognitionException; } diff --git a/Source/mongo/MongoScrapbook.ts b/Source/mongo/MongoScrapbook.ts index 2f441285e..d5dfe6d00 100644 --- a/Source/mongo/MongoScrapbook.ts +++ b/Source/mongo/MongoScrapbook.ts @@ -3,718 +3,489 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - IActionContext, - IParsedError, - openReadOnlyContent, - parseError, - ReadOnlyContent, -} from "@microsoft/vscode-azext-utils"; -import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; -import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; -import { ErrorNode } from "antlr4ts/tree/ErrorNode"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ObjectID } from "bson"; -import { Collection } from "mongodb"; -import { EOL } from "os"; -import * as vscode from "vscode"; -import { ext } from "../extensionVariables"; -import { filterType, findType } from "../utils/array"; -import { localize } from "../utils/localize"; -import { nonNullProp, nonNullValue } from "../utils/nonNull"; -import { LexerErrorListener, ParserErrorListener } from "./errorListeners"; -import { mongoLexer } from "./grammar/mongoLexer"; -import * as mongoParser from "./grammar/mongoParser"; -import { MongoVisitor } from "./grammar/visitors"; -import { ErrorDescription, MongoCommand } from "./MongoCommand"; -import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; -import { - MongoDatabaseTreeItem, - stripQuotes, -} from "./tree/MongoDatabaseTreeItem"; -import { - IMongoDocument, - MongoDocumentTreeItem, -} from "./tree/MongoDocumentTreeItem"; +import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; +import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; +import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { ObjectID } from 'bson'; +import { Collection } from 'mongodb'; +import { EOL } from 'os'; +import * as vscode from 'vscode'; +import { ext } from '../extensionVariables'; +import { filterType, findType } from '../utils/array'; +import { localize } from '../utils/localize'; +import { nonNullProp, nonNullValue } from '../utils/nonNull'; +import { LexerErrorListener, ParserErrorListener } from './errorListeners'; +import { mongoLexer } from './grammar/mongoLexer'; +import * as mongoParser from './grammar/mongoParser'; +import { MongoVisitor } from './grammar/visitors'; +import { ErrorDescription, MongoCommand } from './MongoCommand'; +import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; +import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; +import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); -const notInScrapbookMessage = - "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument( - document: vscode.TextDocument -): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of command.errors || []) { - const diagnostic = new vscode.Diagnostic( - error.range, - error.message - ); - errors.push(diagnostic); - } - } - - return errors; +const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; + +export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { + const commands = getAllCommandsFromTextDocument(document); + const errors: vscode.Diagnostic[] = []; + for (const command of commands) { + for (const error of (command.errors || [])) { + const diagnostic = new vscode.Diagnostic(error.range, error.message); + errors.push(diagnostic); + } + } + + return errors; } -export async function executeAllCommandsFromActiveEditor( - context: IActionContext -): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); +export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { + ext.outputChannel.appendLog("Executing all commands in scrapbook..."); + const commands = getAllCommandsFromActiveEditor(); + await executeCommands(context, commands); } -export async function executeCommandFromActiveEditor( - context: IActionContext, - position?: vscode.Position -): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition( - commands, - position || vscode.window.activeTextEditor?.selection.start - ); - return await executeCommand(context, command); +export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { + const commands = getAllCommandsFromActiveEditor(); + const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); + return await executeCommand(context, command); } function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } + const activeEditor = vscode.window.activeTextEditor; + if (activeEditor) { + return getAllCommandsFromTextDocument(activeEditor.document); + } else { + // Shouldn't be able to reach this + throw new Error(notInScrapbookMessage); + } } -export function getAllCommandsFromTextDocument( - document: vscode.TextDocument -): MongoCommand[] { - return getAllCommandsFromText(document.getText()); +export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { + return getAllCommandsFromText(document.getText()); } -async function executeCommands( - context: IActionContext, - commands: MongoCommand[] -): Promise { - const label: string = "Scrapbook-execute-all-results"; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent( - { label, fullId }, - "", - ".txt", - { viewColumn: vscode.ViewColumn.Beside } - ); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split("(")[0]} at ${ - command.range.start.line + 1 - }:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } +async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { + const label: string = 'Scrapbook-execute-all-results'; + const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; + const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); + + for (const command of commands) { + try { + await executeCommand(context, command, readOnlyContent); + } catch (e) { + const err = parseError(e); + if (err.isUserCancelledError) { + throw e; + } else { + const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; + throw new Error(message); + } + } + } } -async function executeCommand( - context: IActionContext, - command: MongoCommand, - readOnlyContent?: ReadOnlyContent -): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String( - command.arguments ? command.arguments.length : 0 - ); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error( - 'Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item' - ); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error( - localize( - "unableToParseSyntax", - `Unable to parse syntax. Error near line ${ - err.range.start.line + 1 - }, column ${err.range.start.character + 1}: "${ - err.message - }"` - ) - ); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === "find" && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, "collection"); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem( - database, - collection, - command.argumentObjects - ); - await ext.fileSystem.showTextDocument(node, { - viewColumn: vscode.ViewColumn.Beside, - }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === "findOne") { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp( - command, - "collection" - ); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - collectionId, - context - ); - if (!colNode) { - throw new Error( - localize( - "failedToFind", - 'Failed to find collection "{0}".', - collectionName - ) - ); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { - viewColumn: vscode.ViewColumn.Beside, - }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = "Scrapbook-results"; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent( - { label, fullId }, - result, - ".json", - { viewColumn: vscode.ViewColumn.Beside } - ); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error( - "No MongoDB command found at the current cursor location." - ); - } +async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { + if (command) { + try { + context.telemetry.properties.command = command.name; + context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); + } catch (error) { + // Ignore + } + + const database = ext.connectedMongoDB; + if (!database) { + throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); + } + if (command.errors && command.errors.length > 0) { + //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. + const err = command.errors[0]; + throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); + } + + // we don't handle chained commands so we can only handle "find" if isn't chained + if (command.name === 'find' && !command.chained) { + const db = await database.connectToDb(); + const collectionName: string = nonNullProp(command, 'collection'); + const collection: Collection = db.collection(collectionName); + // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because + // the executed 'find' command could have a filter or projection that is not handled by a cached tree node + const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); + await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); + } else { + const result = await database.executeCommand(command, context); + if (command.name === 'findOne') { + if (result === "null") { + throw new Error(`Could not find any documents`); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const document: IMongoDocument = EJSON.parse(result); + const collectionName: string = nonNullProp(command, 'collection'); + + const collectionId: string = `${database.fullId}/${collectionName}`; + const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); + if (!colNode) { + throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); + } + const docNode = new MongoDocumentTreeItem(colNode, document); + await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); + } else { + if (readOnlyContent) { + await readOnlyContent.append(`${result}${EOL}${EOL}`); + } else { + const label: string = 'Scrapbook-results'; + const fullId: string = `${database.fullId}/${label}`; + await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); + } + + await refreshTreeAfterCommand(database, command, context); + } + } + } else { + throw new Error('No MongoDB command found at the current cursor location.'); + } } -async function refreshTreeAfterCommand( - database: MongoDatabaseTreeItem, - command: MongoCommand, - context: IActionContext -): Promise { - if (command.name === "drop") { - await database.refresh(context); - } else if ( - command.collection && - command.name && - /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test( - command.name - ) - ) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem( - database.fullId + "/" + command.collection, - context - ); - if (collectionNode) { - await collectionNode.refresh(context); - } - } +async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { + if (command.name === 'drop') { + await database.refresh(context); + } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { + const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); + if (collectionNode) { + await collectionNode.refresh(context); + } + } } export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = - parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition( - commands, - err.range.start - ); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "", - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; + const lexer = new mongoLexer(new InputStream(content)); + const lexerListener = new LexerErrorListener(); + lexer.removeErrorListeners(); // Default listener outputs to the console + lexer.addErrorListener(lexerListener); + const tokens: CommonTokenStream = new CommonTokenStream(lexer); + + const parser = new mongoParser.mongoParser(tokens); + const parserListener = new ParserErrorListener(); + parser.removeErrorListeners(); // Default listener outputs to the console + parser.addErrorListener(parserListener); + + const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); + const commands = new FindMongoCommandsVisitor().visit(commandsContext); + + // Match errors with commands based on location + const errors = lexerListener.errors.concat(parserListener.errors); + errors.sort((a, b) => { + const linediff = a.range.start.line - b.range.start.line; + const chardiff = a.range.start.character - b.range.start.character; + return linediff || chardiff; + }); + for (const err of errors) { + const associatedCommand = findCommandAtPosition(commands, err.range.start); + if (associatedCommand) { + associatedCommand.errors = associatedCommand.errors || []; + associatedCommand.errors.push(err); + } else { + // Create a new command to hook this up to + const emptyCommand: MongoCommand = { + collection: undefined, + name: undefined, + range: err.range, + text: "" + }; + emptyCommand.errors = [err]; + commands.push(emptyCommand); + } + } + + return commands; } -export function findCommandAtPosition( - commands: MongoCommand[], - position?: vscode.Position -): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return ( - lastCommandOnSameLine || - lastCommandBeforePosition || - commands[commands.length - 1] - ); +export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { + let lastCommandOnSameLine: MongoCommand | undefined; + let lastCommandBeforePosition: MongoCommand | undefined; + if (position) { + for (const command of commands) { + if (command.range.contains(position)) { + return command; + } + if (command.range.end.line === position.line) { + lastCommandOnSameLine = command; + } + if (command.range.end.isBefore(position)) { + lastCommandBeforePosition = command; + } + } + } + return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; } class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType( - ctx.children, - mongoParser.FunctionCallContext - ).length; - const stop = nonNullProp(ctx, "stop"); - this.commands.push({ - range: new vscode.Range( - ctx.start.line - 1, - ctx.start.charPositionInLine, - stop.line - 1, - stop.charPositionInLine - ), - text: ctx.text, - name: "", - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false, - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall( - ctx: mongoParser.FunctionCallContext - ): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = - (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if ( - functionCallContext && - functionCallContext.parent instanceof - mongoParser.CommandContext - ) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, "arguments").push(argText); - const escapeHandled = - this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { - //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, "argumentObjects").push( - ejsonParsed - ); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): Object { - if (!ctx || ctx.childCount === 0) { - //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, "children")[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand( - `Unrecognized node type encountered. We could not parse ${child.text}`, - ctx - ); - return {}; - } - } - - private literalContextToObject( - child: mongoParser.LiteralContext, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [ - mongoParser.mongoParser.NullLiteral, - mongoParser.mongoParser.BooleanLiteral, - mongoParser.mongoParser.NumericLiteral, - ]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand( - `Unrecognized token. Token text: ${text}`, - ctx - ); - return {}; - } - } - - private objectLiteralContextToObject( - child: mongoParser.ObjectLiteralContext - ): Object { - const propertyNameAndValue = findType( - child.children, - mongoParser.PropertyNameAndValueListContext - ); - if (!propertyNameAndValue) { - // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType( - propertyNameAndValue.children, - mongoParser.PropertyAssignmentContext - ); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp( - propertyAssignment, - "children" - ); - const propertyName = ( - propertyAssignmentChildren[0] - ); - const propertyValue = ( - propertyAssignmentChildren[2] - ); - parsedObject[stripQuotes(propertyName.text)] = - this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject( - child: mongoParser.ArrayLiteralContext - ) { - const elementList = findType( - child.children, - mongoParser.ElementListContext - ); - if (elementList) { - const elementItems = filterType( - elementList.children, - mongoParser.PropertyValueContext - ); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject( - child: mongoParser.FunctionCallContext, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue( - findType(functionTokens, TerminalNode), - "constructorCall" - ); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue( - findType(functionTokens, mongoParser.ArgumentsContext), - "argumentsToken" - ); - if ( - !( - argumentsToken._CLOSED_PARENTHESIS && - argumentsToken._OPEN_PARENTHESIS - ) - ) { - //argumentsToken does not have '(' or ')' - this.addErrorToCommand( - `Expecting parentheses or quotes at '${constructorCall.text}'`, - ctx - ); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType( - argumentsToken.children, - mongoParser.ArgumentContext - ); - if (argumentContextArray.length > 1) { - this.addErrorToCommand( - `Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, - ctx - ); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length - ? argumentContextArray[0].text - : undefined; - switch (constructorCall.text) { - case "ObjectId": - return this.objectIdToObject(ctx, tokenText); - case "ISODate": - return this.isodateToObject(ctx, tokenText); - case "Date": - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand( - `Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, - ctx - ); - return {}; - } - } - - private dateToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string - ): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string - ): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string, - isIsodate: boolean = false - ): Date | {} { - if (!tokenText) { - // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== "Z") { - tokenText += "Z"; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string - ): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { - // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - text: string - ): Object { - const separator = text.lastIndexOf("/"); - const flags = - separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { - $regex: this.regexToStringNotation(pattern), - $options: flags, - }; - } catch (error) { - //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand( - errorMessage: string, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, "stop"); - const currentErrorDesc: ErrorDescription = { - message: errorMessage, - range: new vscode.Range( - ctx.start.line - 1, - ctx.start.charPositionInLine, - stop.line - 1, - stop.charPositionInLine - ), - }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, "\\\\$1"); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* + private commands: MongoCommand[] = []; + + public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { + const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; + const stop = nonNullProp(ctx, 'stop'); + this.commands.push({ + range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), + text: ctx.text, + name: '', + arguments: [], + argumentObjects: [], + chained: funcCallCount > 1 ? true : false + }); + return super.visitCommand(ctx); + } + + public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { + this.commands[this.commands.length - 1].collection = ctx.text; + return super.visitCollection(ctx); + } + + public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { + if (ctx.parent instanceof mongoParser.CommandContext) { + this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; + } + return super.visitFunctionCall(ctx); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { + try { + const argumentsContext = ctx.parent; + if (argumentsContext) { + const functionCallContext = argumentsContext.parent; + if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { + const lastCommand = this.commands[this.commands.length - 1]; + const argAsObject = this.contextToObject(ctx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const argText = EJSON.stringify(argAsObject); + nonNullProp(lastCommand, 'arguments').push(argText); + const escapeHandled = this.deduplicateEscapesForRegex(argText); + let ejsonParsed = {}; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + ejsonParsed = EJSON.parse(escapeHandled); + } catch (error) { //EJSON parse failed due to a wrong flag, etc. + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); + } + } + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + return super.visitArgument(ctx); + } + + protected defaultResult(_node: ParseTree): MongoCommand[] { + return this.commands; + } + + private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { + if (!ctx || ctx.childCount === 0) { //Base case and malformed statements + return {}; + } + // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 + const child: ParseTree = nonNullProp(ctx, 'children')[0]; + if (child instanceof mongoParser.LiteralContext) { + return this.literalContextToObject(child, ctx); + } else if (child instanceof mongoParser.ObjectLiteralContext) { + return this.objectLiteralContextToObject(child); + } else if (child instanceof mongoParser.ArrayLiteralContext) { + return this.arrayLiteralContextToObject(child); + } else if (child instanceof mongoParser.FunctionCallContext) { + return this.functionCallContextToObject(child, ctx); + } else if (child instanceof ErrorNode) { + return {}; + } else { + this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); + return {}; + } + } + + private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { + const text = child.text; + const tokenType = child.start.type; + const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; + if (tokenType === mongoParser.mongoParser.StringLiteral) { + return stripQuotes(text); + } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { + return this.regexLiteralContextToObject(ctx, text); + } else if (nonStringLiterals.indexOf(tokenType) > -1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return JSON.parse(text); + } else { + this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); + return {}; + } + } + + private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { + const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); + if (!propertyNameAndValue) { // Argument is {} + return {}; + } else { + const parsedObject: Object = {}; + const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); + for (const propertyAssignment of propertyAssignments) { + const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); + const propertyName = propertyAssignmentChildren[0]; + const propertyValue = propertyAssignmentChildren[2]; + parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); + } + return parsedObject; + } + } + + private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { + const elementList = findType(child.children, mongoParser.ElementListContext); + if (elementList) { + const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); + return elementItems.map(this.contextToObject.bind(this)); + } else { + return []; + } + } + + private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { + const functionTokens = child.children; + const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); + const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); + if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' + this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); + return {}; + } + + const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); + if (argumentContextArray.length > 1) { + this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); + return {}; + } + + const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; + switch (constructorCall.text) { + case 'ObjectId': + return this.objectIdToObject(ctx, tokenText); + case 'ISODate': + return this.isodateToObject(ctx, tokenText); + case 'Date': + return this.dateToObject(ctx, tokenText); + default: + this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); + return {}; + } + } + + private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText); + if (date instanceof Date) { + return { $date: date.toString() }; + } else { + return date; + } + } + + private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); + + if (date instanceof Date) { + return { $date: date.toISOString() }; + } else { + return date; + } + } + + private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { + if (!tokenText) { // usage : ObjectID() + return new Date(); + } else { + try { + tokenText = stripQuotes(tokenText); + + // if the tokenText was an isodate, the last char must be Z + if (isIsodate) { + if (tokenText[tokenText.length - 1] !== 'Z') { + tokenText += 'Z'; + } + } + + return new Date(tokenText); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + } + + private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { + let hexID: string; + let constructedObject: ObjectID; + if (!tokenText) { // usage : ObjectID() + constructedObject = new ObjectID(); + } else { + hexID = stripQuotes(tokenText); + try { + constructedObject = new ObjectID(hexID); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + return { $oid: constructedObject.toString() }; + } + + private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { + const separator = text.lastIndexOf('/'); + const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; + const pattern = text.substring(1, separator); + try { + // validate the pattern and flags. + // It is intended for the errors thrown here to be handled by the catch block. + let tokenObject = new RegExp(pattern, flags); + // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars + tokenObject = tokenObject; + // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax + return { $regex: this.regexToStringNotation(pattern), $options: flags }; + } catch (error) { //User may not have finished typing + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + + private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { + const command = this.commands[this.commands.length - 1]; + command.errors = command.errors || []; + const stop = nonNullProp(ctx, 'stop'); + const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; + command.errors.push(currentErrorDesc); + } + + private regexToStringNotation(pattern: string): string { + // The equivalence: + // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" + return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); + } + + private deduplicateEscapesForRegex(argAsString: string): string { + const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; + /* We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } + return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); + } + } diff --git a/Source/mongo/MongoShell.ts b/Source/mongo/MongoShell.ts index 81784f2af..b8f982ee8 100644 --- a/Source/mongo/MongoShell.ts +++ b/Source/mongo/MongoShell.ts @@ -3,216 +3,185 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from "os"; -import * as vscode from "vscode"; -import { InteractiveChildProcess } from "../utils/InteractiveChildProcess"; -import { randomUtils } from "../utils/randomUtils"; -import { getBatchSizeSetting } from "../utils/workspacUtils"; -import { wrapError } from "../utils/wrapError"; +import { parseError } from '@microsoft/vscode-azext-utils'; +import * as os from 'os'; +import * as vscode from 'vscode'; +import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; +import { randomUtils } from '../utils/randomUtils'; +import { getBatchSizeSetting } from '../utils/workspacUtils'; +import { wrapError } from '../utils/wrapError'; -const timeoutMessage = - "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; +const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = "(More)"; +const extensionMoreMessage = '(More)'; -const sentinelBase = "EXECUTION COMPLETED"; +const sentinelBase = 'EXECUTION COMPLETED'; const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { - return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; -} +function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } export class MongoShell extends vscode.Disposable { - constructor( - private _process: InteractiveChildProcess, - private _timeoutSeconds: number - ) { - super(() => this.dispose()); - } - - public static async create( - execPath: string, - execArgs: string[], - connectionString: string, - isEmulator: boolean | undefined, - outputChannel: vscode.OutputChannel, - timeoutSeconds: number - ): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = - await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: "", - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript( - `DBQuery.shellBatchSize = ${getBatchSizeSetting()}` - ); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise( - async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut((text) => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = - removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace( - mongoShellMoreMessage, - extensionMoreMessage - ); - - resolve(stdOutNoSentinel); - } - }) - ); - disposables.push( - this._process.onStdErr((text) => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - }) - ); - disposables.push( - this._process.onError((error) => { - reject(error); - }) - ); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === "EPIPE") { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error( - "The process exited prematurely." - ); - } - - reject(wrapCheckOutputWindow(error)); - } - } - ); - - return result.trim(); - } finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } + + constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { + super(() => this.dispose()); + } + + public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { + try { + const args: string[] = execArgs.slice() || []; // Snapshot since we modify it + args.push(connectionString); + + if (isEmulator) { + // Without these the connection will fail due to the self-signed DocDB certificate + if (args.indexOf("--ssl") < 0) { + args.push("--ssl"); + } + if (args.indexOf("--sslAllowInvalidCertificates") < 0) { + args.push("--sslAllowInvalidCertificates"); + } + } + + const process: InteractiveChildProcess = await InteractiveChildProcess.create({ + outputChannel: outputChannel, + command: execPath, + args, + outputFilterSearch: sentinelRegex, + outputFilterReplace: '' + }); + const shell: MongoShell = new MongoShell(process, timeoutSeconds); + + // Try writing an empty script to verify the process is running correctly and allow us + // to catch any errors related to the start-up of the process before trying to write to it. + await shell.executeScript(""); + + // Configure the batch size + await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); + + return shell; + } catch (error) { + throw wrapCheckOutputWindow(error); + } + } + + public dispose(): void { + this._process.kill(); + } + + public async useDatabase(database: string): Promise { + return await this.executeScript(`use ${database}`); + } + + public async executeScript(script: string): Promise { + script = convertToSingleLine(script); + + let stdOut = ""; + const sentinel = createSentinel(); + + const disposables: vscode.Disposable[] = []; + try { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + const result = await new Promise(async (resolve, reject) => { + try { + startScriptTimeout(this._timeoutSeconds, reject); + + // Hook up events + disposables.push( + this._process.onStdOut(text => { + stdOut += text; + // eslint-disable-next-line prefer-const + let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); + if (removed) { + // The sentinel was found, which means we are done. + + // Change the "type 'it' for more" message to one that doesn't ask users to type anything, + // since we're not currently interactive like that. + // CONSIDER: Ideally we would allow users to click a button to iterate through more data, + // or even just do it for them + stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); + + resolve(stdOutNoSentinel); + } + })); + disposables.push( + this._process.onStdErr(text => { + // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. + // So consider this an error. + // (It's okay if we fire this multiple times, the first one wins.) + reject(wrapCheckOutputWindow(text.trim())); + })); + disposables.push( + this._process.onError(error => { + reject(error); + })); + + // Write the script to STDIN + if (script) { + this._process.writeLine(script); + } + + // Mark end of result by sending the sentinel wrapped in quotes so the console will spit + // it back out as a string value after it's done processing the script + const quotedSentinel = `"${sentinel}"`; + this._process.writeLine(quotedSentinel); // (Don't display the sentinel) + + } catch (error) { + // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it + + if ((<{ code?: string }>error).code === 'EPIPE') { + // Give a chance for start-up errors to show up before rejecting with this more general error message + await delay(500); + // eslint-disable-next-line no-ex-assign + error = new Error("The process exited prematurely."); + } + + reject(wrapCheckOutputWindow(error)); + } + }); + + return result.trim(); + } + finally { + // Dispose event handlers + for (const d of disposables) { + d.dispose(); + } + } + } } -function startScriptTimeout( - timeoutSeconds: number | 0, - reject: (err: unknown) => void -): void { - if (timeoutSeconds > 0) { - setTimeout(() => { - reject(timeoutMessage); - }, timeoutSeconds * 1000); - } +function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { + if (timeoutSeconds > 0) { + setTimeout( + () => { + reject(timeoutMessage); + }, + timeoutSeconds * 1000); + } } function convertToSingleLine(script: string): string { - return script - .split(os.EOL) - .map((line) => line.trim()) - .join(""); + return script.split(os.EOL) + .map(line => line.trim()) + .join(''); + } -function removeSentinel( - text: string, - sentinel: string -): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } +function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { + const index = text.indexOf(sentinel); + if (index >= 0) { + return { text: text.slice(0, index), removed: true }; + } else { + return { text, removed: false }; + } } async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); } function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = - "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) - ? error - : wrapError(error, checkOutputMsg); + const checkOutputMsg = "The output window may contain additional information."; + return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); } diff --git a/Source/mongo/connectToMongoClient.ts b/Source/mongo/connectToMongoClient.ts index e2fe8d5d1..88aa2df17 100644 --- a/Source/mongo/connectToMongoClient.ts +++ b/Source/mongo/connectToMongoClient.ts @@ -3,58 +3,47 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MongoClient, MongoClientOptions } from "mongodb"; -import { emulatorPassword, Links } from "../constants"; - -export async function connectToMongoClient( - connectionString: string, - appName: string -): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true, - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string; name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if ( - message && - /ECONNREFUSED/.test(message) && - /(localhost|127\.0\.0\.1)/.test(message) - ) { - throw new MongoConnectError(); - } - - throw error; - } +import { MongoClient, MongoClientOptions } from 'mongodb'; +import { emulatorPassword, Links } from '../constants'; + +export async function connectToMongoClient(connectionString: string, appName: string): Promise { + // appname appears to be the correct equivalent to user-agent for mongo + const options: MongoClientOptions = { + // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string + appName: `@${appName}@`, + // https://github.com/lmammino/mongo-uri-builder/issues/2 + useNewUrlParser: true, + useUnifiedTopology: true + }; + + if (isCosmosEmulatorConnectionString(connectionString)) { + // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 + options.tlsAllowInvalidCertificates = true; + } + + try { + return await MongoClient.connect(connectionString, options); + } catch (err) { + // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info + const error = <{ message?: string, name?: string }>err; + const message = error && error.message; + + // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" + // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" + if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { + throw new MongoConnectError(); + } + + throw error; + } } export class MongoConnectError extends Error { - constructor() { - super( - `Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.` - ); - } + constructor() { + super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); + } } -export function isCosmosEmulatorConnectionString( - connectionString: string -): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); +export function isCosmosEmulatorConnectionString(connectionString: string): boolean { + return connectionString.includes(encodeURIComponent(emulatorPassword)); } diff --git a/Source/mongo/errorListeners.ts b/Source/mongo/errorListeners.ts index 00d510cd5..ea582d544 100644 --- a/Source/mongo/errorListeners.ts +++ b/Source/mongo/errorListeners.ts @@ -3,65 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRErrorListener } from "antlr4ts/ANTLRErrorListener"; -import { RecognitionException } from "antlr4ts/RecognitionException"; -import { Recognizer } from "antlr4ts/Recognizer"; -import { Token } from "antlr4ts/Token"; +import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; +import { RecognitionException } from 'antlr4ts/RecognitionException'; +import { Recognizer } from 'antlr4ts/Recognizer'; +import { Token } from 'antlr4ts/Token'; import * as vscode from "vscode"; -import { ErrorDescription } from "./MongoCommand"; +import { ErrorDescription } from './MongoCommand'; export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; - public get errors(): ErrorDescription[] { - return this._errors; - } + public get errors(): ErrorDescription[] { + return this._errors; + } - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined - ): void { - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: Token | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined): void { - const error: ErrorDescription = { - message: msg, - range: range, - exception: e, - }; - this._errors.push(error); - } + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); + + const error: ErrorDescription = { + message: msg, + range: range, + exception: e + }; + this._errors.push(error); + } } export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; + + public get errors(): ErrorDescription[] { + return this._errors; + } - public get errors(): ErrorDescription[] { - return this._errors; - } + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: number | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined): void { - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined - ): void { - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const error: ErrorDescription = { - message: msg, - range: range, - exception: e, - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e + }; + this._errors.push(error); + } } diff --git a/Source/mongo/grammar/mongoLexer.ts b/Source/mongo/grammar/mongoLexer.ts index 47b461a6f..3b6cbbdd0 100644 --- a/Source/mongo/grammar/mongoLexer.ts +++ b/Source/mongo/grammar/mongoLexer.ts @@ -9,312 +9,239 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from "antlr4ts/atn/ATN"; -import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; -import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; -import { CharStream } from "antlr4ts/CharStream"; -import { NotNull, Override } from "antlr4ts/Decorators"; -import { Lexer } from "antlr4ts/Lexer"; -import * as Utils from "antlr4ts/misc/Utils"; -import { RuleContext } from "antlr4ts/RuleContext"; -import { Vocabulary } from "antlr4ts/Vocabulary"; -import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +import { ATN } from 'antlr4ts/atn/ATN'; +import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; +import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; +import { CharStream } from 'antlr4ts/CharStream'; +import { NotNull, Override } from 'antlr4ts/Decorators'; +import { Lexer } from 'antlr4ts/Lexer'; +import * as Utils from 'antlr4ts/misc/Utils'; +import { RuleContext } from 'antlr4ts/RuleContext'; +import { Vocabulary } from 'antlr4ts/Vocabulary'; +import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = ["DEFAULT_MODE"]; - - public static readonly ruleNames: string[] = [ - "T__0", - "T__1", - "T__2", - "T__3", - "T__4", - "T__5", - "T__6", - "T__7", - "RegexLiteral", - "RegexFlag", - "SingleLineComment", - "MultiLineComment", - "StringLiteral", - "NullLiteral", - "BooleanLiteral", - "NumericLiteral", - "DecimalLiteral", - "LineTerminator", - "SEMICOLON", - "DOT", - "DB", - "IDENTIFIER", - "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", - "STRING_ESCAPE", - "DecimalIntegerLiteral", - "ExponentPart", - "DecimalDigit", - "WHITESPACE", - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, - "'('", - "','", - "')'", - "'{'", - "'}'", - "'['", - "']'", - "':'", - undefined, - undefined, - undefined, - undefined, - "'null'", - undefined, - undefined, - undefined, - undefined, - "';'", - "'.'", - "'db'", - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - "RegexLiteral", - "SingleLineComment", - "MultiLineComment", - "StringLiteral", - "NullLiteral", - "BooleanLiteral", - "NumericLiteral", - "DecimalLiteral", - "LineTerminator", - "SEMICOLON", - "DOT", - "DB", - "IDENTIFIER", - "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", - "WHITESPACE", - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( - mongoLexer._LITERAL_NAMES, - mongoLexer._SYMBOLIC_NAMES, - [] - ); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - private isExternalIdentifierText(text) { - return text === "db"; - } - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - @Override - public get grammarFileName(): string { - return "mongo.g4"; - } - @Override - public get ruleNames(): string[] { - return mongoLexer.ruleNames; - } - - @Override - public get serializedATN(): string { - return mongoLexer._serializedATN; - } - - @Override - public get modeNames(): string[] { - return mongoLexer.modeNames; - } - - @Override - public sempred( - _localctx: RuleContext, - ruleIndex: number, - predIndex: number - ): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred( - _localctx: RuleContext, - predIndex: number - ): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text); - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - 'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - 'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - '\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize( - Utils.toCharArray(mongoLexer._serializedATN) - ); - } +export class mongoLexer extends Lexer { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly modeNames: string[] = [ + "DEFAULT_MODE" + ]; + + public static readonly ruleNames: string[] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", + "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", + "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", + "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", + "ExponentPart", "DecimalDigit", "WHITESPACE" + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, + undefined, undefined, undefined, "'null'", undefined, undefined, undefined, + undefined, "';'", "'.'", "'db'" + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", + "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", + "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoLexer.VOCABULARY; + } + + + private isExternalIdentifierText(text) { + return text === 'db'; + } + + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(mongoLexer._ATN, this); + } + + @Override + public get grammarFileName(): string { return "mongo.g4"; } + + @Override + public get ruleNames(): string[] { return mongoLexer.ruleNames; } + + @Override + public get serializedATN(): string { return mongoLexer._serializedATN; } + + @Override + public get modeNames(): string[] { return mongoLexer.modeNames; } + + @Override + public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 21: + return this.IDENTIFIER_sempred(_localctx, predIndex); + } + return true; + } + private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { + switch (predIndex) { + case 0: + return !this.isExternalIdentifierText(this.text) + ; + } + return true; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + + "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + + "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + + "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + + "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + + "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + + "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + + "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + + "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + + "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + + "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + + "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + + "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + + "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + + "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + + "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + + "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + + "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + + "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + + "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + + "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + + "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + + "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + + "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + + "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + + "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + + "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + + "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + + "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + + "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + + "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + + "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + + "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + + "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + + "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + + "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + + "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + + "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + + ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + + "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + + "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + + "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + + "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + + "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + + "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + + "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + + "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + + "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + + "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + + "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + + "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + + "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + + "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + + "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + + "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + + "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + + "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + + "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + + "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + + "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + + "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + + "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + + "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + + "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + + "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + + "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + + "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + + "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + + "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + + "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + + "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + + "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + + "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + + "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + + "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + + "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + + "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + + "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + + "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + + "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + + "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + + "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + + "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + + "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + + "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + + "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + + "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + + "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + + "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + + "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + + "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + + "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + + "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + + "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + + "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + + "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + + "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + + "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + + "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + + "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + + "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + + "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + + "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + + "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + + "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + + "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + + "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + + "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + + "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + + "\x04\x02\x03\x02\b\x02\x02"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoLexer.__ATN) { + mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); + } + + return mongoLexer.__ATN; + } - return mongoLexer.__ATN; - } } + diff --git a/Source/mongo/grammar/mongoListener.ts b/Source/mongo/grammar/mongoListener.ts index d1d8ffac8..43514f500 100644 --- a/Source/mongo/grammar/mongoListener.ts +++ b/Source/mongo/grammar/mongoListener.ts @@ -1,30 +1,17 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { - ArgumentContext, - ArgumentsContext, - ArrayLiteralContext, - CollectionContext, - CommandContext, - CommandsContext, - CommentContext, - ElementListContext, - EmptyCommandContext, - FunctionCallContext, - LiteralContext, - MongoCommandsContext, - ObjectLiteralContext, - PropertyAssignmentContext, - PropertyNameAndValueListContext, - PropertyNameContext, - PropertyValueContext, -} from "./mongoParser"; + + +import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; +import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; + + /** * This interface defines a complete listener for a parse tree produced by @@ -156,16 +143,12 @@ export interface mongoListener extends ParseTreeListener { * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - enterPropertyNameAndValueList?: ( - ctx: PropertyNameAndValueListContext - ) => void; + enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; /** * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - exitPropertyNameAndValueList?: ( - ctx: PropertyNameAndValueListContext - ) => void; + exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; /** * Enter a parse tree produced by `mongoParser.propertyAssignment`. @@ -222,3 +205,4 @@ export interface mongoListener extends ParseTreeListener { */ exitComment?: (ctx: CommentContext) => void; } + diff --git a/Source/mongo/grammar/mongoParser.ts b/Source/mongo/grammar/mongoParser.ts index f08e3ff51..c1d38f4d0 100644 --- a/Source/mongo/grammar/mongoParser.ts +++ b/Source/mongo/grammar/mongoParser.ts @@ -9,1650 +9,1458 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from "antlr4ts/atn/ATN"; -import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; -import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; -import { NotNull, Override } from "antlr4ts/Decorators"; -import * as Utils from "antlr4ts/misc/Utils"; -import { NoViableAltException } from "antlr4ts/NoViableAltException"; -import { Parser } from "antlr4ts/Parser"; -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { RecognitionException } from "antlr4ts/RecognitionException"; -import { RuleVersion } from "antlr4ts/RuleVersion"; -import { Token } from "antlr4ts/Token"; -import { TokenStream } from "antlr4ts/TokenStream"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Vocabulary } from "antlr4ts/Vocabulary"; -import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; -import { mongoListener } from "./mongoListener"; -import { mongoVisitor } from "./mongoVisitor"; +import { ATN } from 'antlr4ts/atn/ATN'; +import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; +import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; +import { NotNull, Override } from 'antlr4ts/Decorators'; +import * as Utils from 'antlr4ts/misc/Utils'; +import { NoViableAltException } from 'antlr4ts/NoViableAltException'; +import { Parser } from 'antlr4ts/Parser'; +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { RecognitionException } from 'antlr4ts/RecognitionException'; +import { RuleVersion } from 'antlr4ts/RuleVersion'; +import { Token } from 'antlr4ts/Token'; +import { TokenStream } from 'antlr4ts/TokenStream'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { Vocabulary } from 'antlr4ts/Vocabulary'; +import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; +import { mongoListener } from './mongoListener'; +import { mongoVisitor } from './mongoVisitor'; + + + export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", - "commands", - "command", - "emptyCommand", - "collection", - "functionCall", - "arguments", - "argument", - "objectLiteral", - "arrayLiteral", - "elementList", - "propertyNameAndValueList", - "propertyAssignment", - "propertyValue", - "literal", - "propertyName", - "comment", - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, - "'('", - "','", - "')'", - "'{'", - "'}'", - "'['", - "']'", - "':'", - undefined, - undefined, - undefined, - undefined, - "'null'", - undefined, - undefined, - undefined, - undefined, - "';'", - "'.'", - "'db'", - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - "RegexLiteral", - "SingleLineComment", - "MultiLineComment", - "StringLiteral", - "NullLiteral", - "BooleanLiteral", - "NumericLiteral", - "DecimalLiteral", - "LineTerminator", - "SEMICOLON", - "DOT", - "DB", - "IDENTIFIER", - "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", - "WHITESPACE", - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( - mongoParser._LITERAL_NAMES, - mongoParser._SYMBOLIC_NAMES, - [] - ); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { - return "mongo.g4"; - } - - @Override - public get ruleNames(): string[] { - return mongoParser.ruleNames; - } - - @Override - public get serializedATN(): string { - return mongoParser._serializedATN; - } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.SingleLineComment) | - (1 << mongoParser.MultiLineComment) | - (1 << mongoParser.SEMICOLON) | - (1 << mongoParser.DB))) !== - 0 - ) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch ( - this.interpreter.adaptivePredict(this._input, 2, this._ctx) - ) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch ( - this.interpreter.adaptivePredict(this._input, 4, this._ctx) - ) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 5, - this._ctx - ); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 5, - this._ctx - ); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.T__3) | - (1 << mongoParser.T__5) | - (1 << mongoParser.RegexLiteral) | - (1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral) | - (1 << mongoParser.NumericLiteral))) !== - 0 - ) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - _la === mongoParser.StringLiteral || - _la === mongoParser.IDENTIFIER - ) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.T__3) | - (1 << mongoParser.T__5) | - (1 << mongoParser.RegexLiteral) | - (1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral) | - (1 << mongoParser.NumericLiteral) | - (1 << mongoParser.IDENTIFIER))) !== - 0 - ) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = - new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule( - _localctx, - 22, - mongoParser.RULE_propertyNameAndValueList - ); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 13, - this._ctx - ); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 13, - this._ctx - ); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = - new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if ( - !( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral))) !== - 0 - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if ( - !( - _la === mongoParser.StringLiteral || - _la === mongoParser.IDENTIFIER - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if ( - !( - _la === mongoParser.SingleLineComment || - _la === mongoParser.MultiLineComment - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - '\x1C\x02\x1E\x02 \x02"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17' + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - '\x02\x02"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03' + - "\x03\x02\x02\x02'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize( - Utils.toCharArray(mongoParser._serializedATN) - ); - } - - return mongoParser.__ATN; - } + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly RULE_mongoCommands = 0; + public static readonly RULE_commands = 1; + public static readonly RULE_command = 2; + public static readonly RULE_emptyCommand = 3; + public static readonly RULE_collection = 4; + public static readonly RULE_functionCall = 5; + public static readonly RULE_arguments = 6; + public static readonly RULE_argument = 7; + public static readonly RULE_objectLiteral = 8; + public static readonly RULE_arrayLiteral = 9; + public static readonly RULE_elementList = 10; + public static readonly RULE_propertyNameAndValueList = 11; + public static readonly RULE_propertyAssignment = 12; + public static readonly RULE_propertyValue = 13; + public static readonly RULE_literal = 14; + public static readonly RULE_propertyName = 15; + public static readonly RULE_comment = 16; + public static readonly ruleNames: string[] = [ + "mongoCommands", "commands", "command", "emptyCommand", "collection", + "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", + "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", + "literal", "propertyName", "comment" + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, + undefined, undefined, undefined, "'null'", undefined, undefined, undefined, + undefined, "';'", "'.'", "'db'" + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", + "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", + "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoParser.VOCABULARY; + } + + @Override + public get grammarFileName(): string { return "mongo.g4"; } + + @Override + public get ruleNames(): string[] { return mongoParser.ruleNames; } + + @Override + public get serializedATN(): string { return mongoParser._serializedATN; } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(mongoParser._ATN, this); + } + @RuleVersion(0) + public mongoCommands(): MongoCommandsContext { + const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); + this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 34; + this.commands(); + this.state = 35; + this.match(mongoParser.EOF); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public commands(): CommandsContext { + const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); + this.enterRule(_localctx, 2, mongoParser.RULE_commands); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 42; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { + { + this.state = 40; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.DB: + { + this.state = 37; + this.command(); + } + break; + case mongoParser.SEMICOLON: + { + this.state = 38; + this.emptyCommand(); + } + break; + case mongoParser.SingleLineComment: + case mongoParser.MultiLineComment: + { + this.state = 39; + this.comment(); + } + break; + default: + throw new NoViableAltException(this); + } + } + this.state = 44; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public command(): CommandContext { + const _localctx: CommandContext = new CommandContext(this._ctx, this.state); + this.enterRule(_localctx, 4, mongoParser.RULE_command); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 45; + this.match(mongoParser.DB); + this.state = 48; + this._errHandler.sync(this); + switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { + case 1: + { + this.state = 46; + this.match(mongoParser.DOT); + this.state = 47; + this.collection(); + } + break; + } + this.state = 52; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 50; + this.match(mongoParser.DOT); + this.state = 51; + this.functionCall(); + } + } + this.state = 54; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la === mongoParser.DOT); + this.state = 57; + this._errHandler.sync(this); + switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { + case 1: + { + this.state = 56; + this.match(mongoParser.SEMICOLON); + } + break; + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public emptyCommand(): EmptyCommandContext { + const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 59; + this.match(mongoParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public collection(): CollectionContext { + const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); + this.enterRule(_localctx, 8, mongoParser.RULE_collection); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 61; + this.match(mongoParser.IDENTIFIER); + this.state = 66; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 62; + this.match(mongoParser.DOT); + this.state = 63; + this.match(mongoParser.IDENTIFIER); + } + } + } + this.state = 68; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public functionCall(): FunctionCallContext { + const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); + this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 69; + _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); + this.state = 70; + this.arguments(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arguments(): ArgumentsContext { + const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); + this.enterRule(_localctx, 12, mongoParser.RULE_arguments); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 72; + _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); + this.state = 81; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { + { + this.state = 73; + this.argument(); + this.state = 78; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 74; + this.match(mongoParser.T__1); + this.state = 75; + this.argument(); + } + } + this.state = 80; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + this.state = 83; + _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public argument(): ArgumentContext { + const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); + this.enterRule(_localctx, 14, mongoParser.RULE_argument); + try { + this.state = 88; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 85; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 86; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 87; + this.arrayLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public objectLiteral(): ObjectLiteralContext { + const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); + this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 90; + this.match(mongoParser.T__3); + this.state = 92; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { + { + this.state = 91; + this.propertyNameAndValueList(); + } + } + + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.T__1) { + { + this.state = 94; + this.match(mongoParser.T__1); + } + } + + this.state = 97; + this.match(mongoParser.T__4); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arrayLiteral(): ArrayLiteralContext { + const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); + this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 99; + this.match(mongoParser.T__5); + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { + { + this.state = 100; + this.elementList(); + } + } + + this.state = 103; + this.match(mongoParser.T__6); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public elementList(): ElementListContext { + const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); + this.enterRule(_localctx, 20, mongoParser.RULE_elementList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 105; + this.propertyValue(); + this.state = 110; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 106; + this.match(mongoParser.T__1); + this.state = 107; + this.propertyValue(); + } + } + this.state = 112; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyNameAndValueList(): PropertyNameAndValueListContext { + const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); + this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 113; + this.propertyAssignment(); + this.state = 118; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 114; + this.match(mongoParser.T__1); + this.state = 115; + this.propertyAssignment(); + } + } + } + this.state = 120; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyAssignment(): PropertyAssignmentContext { + const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); + this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 121; + this.propertyName(); + this.state = 122; + this.match(mongoParser.T__7); + this.state = 123; + this.propertyValue(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyValue(): PropertyValueContext { + const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); + this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); + try { + this.state = 129; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 125; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 126; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 127; + this.arrayLiteral(); + } + break; + case mongoParser.IDENTIFIER: + this.enterOuterAlt(_localctx, 4); + { + this.state = 128; + this.functionCall(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public literal(): LiteralContext { + const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); + this.enterRule(_localctx, 28, mongoParser.RULE_literal); + let _la: number; + try { + this.state = 134; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 131; + _la = this._input.LA(1); + if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + break; + case mongoParser.RegexLiteral: + this.enterOuterAlt(_localctx, 2); + { + this.state = 132; + this.match(mongoParser.RegexLiteral); + } + break; + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 3); + { + this.state = 133; + this.match(mongoParser.NumericLiteral); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyName(): PropertyNameContext { + const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); + this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 136; + _la = this._input.LA(1); + if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public comment(): CommentContext { + const _localctx: CommentContext = new CommentContext(this._ctx, this.state); + this.enterRule(_localctx, 32, mongoParser.RULE_comment); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 138; + _la = this._input.LA(1); + if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + + "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + + "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + + "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + + "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + + "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + + "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + + "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + + "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + + "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + + "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + + "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + + "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + + "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + + "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + + "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + + "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + + "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + + "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + + "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + + ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + + "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + + "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + + "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + + "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + + "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + + "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + + "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + + "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + + "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + + "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + + "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + + "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + + "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + + "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + + "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + + "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + + "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + + "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + + "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + + "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + + "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + + "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + + "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + + "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + + "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + + "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + + "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + + "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + + "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + + "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + + "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoParser.__ATN) { + mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); + } + + return mongoParser.__ATN; + } + } export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { - return this.getToken(mongoParser.EOF, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_mongoCommands; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } + public commands(): CommandsContext { + return this.getRuleContext(0, CommandsContext); + } + public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterMongoCommands) listener.enterMongoCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitMongoCommands) listener.exitMongoCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); + else return visitor.visitChildren(this); + } } + export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand( - i?: number - ): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_commands; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } + public command(): CommandContext[]; + public command(i: number): CommandContext; + public command(i?: number): CommandContext | CommandContext[] { + if (i === undefined) { + return this.getRuleContexts(CommandContext); + } else { + return this.getRuleContext(i, CommandContext); + } + } + public emptyCommand(): EmptyCommandContext[]; + public emptyCommand(i: number): EmptyCommandContext; + public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { + if (i === undefined) { + return this.getRuleContexts(EmptyCommandContext); + } else { + return this.getRuleContext(i, EmptyCommandContext); + } + } + public comment(): CommentContext[]; + public comment(i: number): CommentContext; + public comment(i?: number): CommentContext | CommentContext[] { + if (i === undefined) { + return this.getRuleContexts(CommentContext); + } else { + return this.getRuleContext(i, CommentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommands) listener.enterCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommands) listener.exitCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommands) return visitor.visitCommands(this); + else return visitor.visitChildren(this); + } } + export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { - return this.getToken(mongoParser.DB, 0); - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall( - i?: number - ): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.SEMICOLON, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_command; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } + public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + public collection(): CollectionContext | undefined { + return this.tryGetRuleContext(0, CollectionContext); + } + public functionCall(): FunctionCallContext[]; + public functionCall(i: number): FunctionCallContext; + public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionCallContext); + } else { + return this.getRuleContext(i, FunctionCallContext); + } + } + public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_command; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommand) listener.enterCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommand) listener.exitCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommand) return visitor.visitCommand(this); + else return visitor.visitChildren(this); + } } + export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { - return this.getToken(mongoParser.SEMICOLON, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_emptyCommand; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } + public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); + else return visitor.visitChildren(this); + } } + export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_collection; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.IDENTIFIER); + } else { + return this.getToken(mongoParser.IDENTIFIER, i); + } + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCollection) listener.enterCollection(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCollection) listener.exitCollection(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCollection) return visitor.visitCollection(this); + else return visitor.visitChildren(this); + } } + export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { - return this.getToken(mongoParser.IDENTIFIER, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_functionCall; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } + public _FUNCTION_NAME: Token; + public arguments(): ArgumentsContext { + return this.getRuleContext(0, ArgumentsContext); + } + public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterFunctionCall) listener.enterFunctionCall(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitFunctionCall) listener.exitFunctionCall(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); + else return visitor.visitChildren(this); + } } + export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_arguments; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } + public _OPEN_PARENTHESIS: Token; + public _CLOSED_PARENTHESIS: Token; + public argument(): ArgumentContext[]; + public argument(i: number): ArgumentContext; + public argument(i?: number): ArgumentContext | ArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(ArgumentContext); + } else { + return this.getRuleContext(i, ArgumentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArguments) listener.enterArguments(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArguments) listener.exitArguments(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArguments) return visitor.visitArguments(this); + else return visitor.visitChildren(this); + } } + export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_argument; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArgument) listener.enterArgument(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArgument) listener.exitArgument(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArgument) return visitor.visitArgument(this); + else return visitor.visitChildren(this); + } } + export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): - | PropertyNameAndValueListContext - | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_objectLiteral; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } + public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { + return this.tryGetRuleContext(0, PropertyNameAndValueListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); + else return visitor.visitChildren(this); + } } + export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_arrayLiteral; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } + public elementList(): ElementListContext | undefined { + return this.tryGetRuleContext(0, ElementListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); + else return visitor.visitChildren(this); + } } + export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue( - i?: number - ): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_elementList; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } + public propertyValue(): PropertyValueContext[]; + public propertyValue(i: number): PropertyValueContext; + public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyValueContext); + } else { + return this.getRuleContext(i, PropertyValueContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterElementList) listener.enterElementList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitElementList) listener.exitElementList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitElementList) return visitor.visitElementList(this); + else return visitor.visitChildren(this); + } } + export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment( - i?: number - ): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyNameAndValueList; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) - listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) - listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) - return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } + public propertyAssignment(): PropertyAssignmentContext[]; + public propertyAssignment(i: number): PropertyAssignmentContext; + public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyAssignmentContext); + } else { + return this.getRuleContext(i, PropertyAssignmentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); + else return visitor.visitChildren(this); + } } + export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyAssignment; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) - listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) - listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) - return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } + public propertyName(): PropertyNameContext { + return this.getRuleContext(0, PropertyNameContext); + } + public propertyValue(): PropertyValueContext { + return this.getRuleContext(0, PropertyValueContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); + else return visitor.visitChildren(this); + } } + export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyValue; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + public functionCall(): FunctionCallContext | undefined { + return this.tryGetRuleContext(0, FunctionCallContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyValue) listener.enterPropertyValue(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyValue) listener.exitPropertyValue(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); + else return visitor.visitChildren(this); + } } + export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.NullLiteral, 0); - } - public BooleanLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.BooleanLiteral, 0); - } - public StringLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.StringLiteral, 0); - } - public RegexLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.RegexLiteral, 0); - } - public NumericLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.NumericLiteral, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_literal; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } + public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } + public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } + public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } + public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } + public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterLiteral) listener.enterLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitLiteral) listener.exitLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitLiteral) return visitor.visitLiteral(this); + else return visitor.visitChildren(this); + } } + export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.StringLiteral, 0); - } - public IDENTIFIER(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.IDENTIFIER, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyName; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } + public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } + public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyName) listener.enterPropertyName(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyName) listener.exitPropertyName(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyName) return visitor.visitPropertyName(this); + else return visitor.visitChildren(this); + } } + export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.SingleLineComment, 0); - } - public MultiLineComment(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.MultiLineComment, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_comment; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } + public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } + public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterComment) listener.enterComment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitComment) listener.exitComment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitComment) return visitor.visitComment(this); + else return visitor.visitChildren(this); + } } + + diff --git a/Source/mongo/grammar/mongoVisitor.ts b/Source/mongo/grammar/mongoVisitor.ts index 105184d2d..eb001a6e9 100644 --- a/Source/mongo/grammar/mongoVisitor.ts +++ b/Source/mongo/grammar/mongoVisitor.ts @@ -1,30 +1,17 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; -import { - ArgumentContext, - ArgumentsContext, - ArrayLiteralContext, - CollectionContext, - CommandContext, - CommandsContext, - CommentContext, - ElementListContext, - EmptyCommandContext, - FunctionCallContext, - LiteralContext, - MongoCommandsContext, - ObjectLiteralContext, - PropertyAssignmentContext, - PropertyNameAndValueListContext, - PropertyNameContext, - PropertyValueContext, -} from "./mongoParser"; + + +import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; +import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; + + /** * This interface defines a complete generic visitor for a parse tree produced @@ -116,9 +103,7 @@ export interface mongoVisitor extends ParseTreeVisitor { * @param ctx the parse tree * @return the visitor result */ - visitPropertyNameAndValueList?: ( - ctx: PropertyNameAndValueListContext - ) => Result; + visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; /** * Visit a parse tree produced by `mongoParser.propertyAssignment`. @@ -155,3 +140,4 @@ export interface mongoVisitor extends ParseTreeVisitor { */ visitComment?: (ctx: CommentContext) => Result; } + diff --git a/Source/mongo/grammar/visitors.ts b/Source/mongo/grammar/visitors.ts index 20e69315d..e1ba1b63d 100644 --- a/Source/mongo/grammar/visitors.ts +++ b/Source/mongo/grammar/visitors.ts @@ -3,88 +3,81 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ErrorNode } from "antlr4ts/tree/ErrorNode"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { - ArgumentContext, - ArgumentsContext, - CollectionContext, - CommandContext, - CommandsContext, - FunctionCallContext, - MongoCommandsContext, -} from "./mongoParser"; -import { mongoVisitor } from "./mongoVisitor"; +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; +import { mongoVisitor } from './mongoVisitor'; export class MongoVisitor implements mongoVisitor { - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount; - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return (null); - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } + + visitMongoCommands(ctx: MongoCommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommands(ctx: CommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommand(ctx: CommandContext): T { + return this.visitChildren(ctx); + } + + visitCollection(ctx: CollectionContext): T { + return this.visitChildren(ctx); + } + + visitFunctionCall(ctx: FunctionCallContext): T { + return this.visitChildren(ctx); + } + + visitArgument(ctx: ArgumentContext): T { + return this.visitChildren(ctx); + } + + visitArguments(ctx: ArgumentsContext): T { + return this.visitChildren(ctx); + } + + visit(tree: ParseTree): T { + return tree.accept(this); + } + + visitChildren(ctx: ParserRuleContext): T { + let result = this.defaultResult(ctx); + const n = ctx.childCount + for (let i = 0; i < n; i++) { + if (!this.shouldVisitNextChild(ctx, result)) { + break; + } + + const childNode = ctx.getChild(i); + const childResult = childNode.accept(this); + result = this.aggregateResult(result, childResult); + } + return result; + } + + visitTerminal(node: TerminalNode): T { + return this.defaultResult(node); + } + + visitErrorNode(node: ErrorNode): T { + return this.defaultResult(node); + } + + protected defaultResult(_node: ParseTree): T { + // grandfathered-in. Unclear why this is null instead of type T + return null; + } + + protected aggregateResult(aggregate: T, nextResult: T): T { + return !nextResult ? aggregate : nextResult; + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + shouldVisitNextChild(_node, _currentResult: T): boolean { + return true; + } } diff --git a/Source/mongo/languageClient.ts b/Source/mongo/languageClient.ts index 6f445423e..e4bd4aefd 100644 --- a/Source/mongo/languageClient.ts +++ b/Source/mongo/languageClient.ts @@ -2,81 +2,57 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; -import * as path from "path"; -import { - LanguageClient, - LanguageClientOptions, - ServerOptions, - TransportKind, -} from "vscode-languageclient"; -import * as nls from "vscode-nls"; -import { ext } from "../extensionVariables"; -import { IConnectionParams } from "./services/IConnectionParams"; +import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; +import * as path from 'path'; +import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; +import * as nls from 'vscode-nls'; +import { ext } from '../extensionVariables'; +import { IConnectionParams } from './services/IConnectionParams'; const localize = nls.loadMessageBundle(); export class MongoDBLanguageClient { - public client: LanguageClient; - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle - ? ext.context.asAbsolutePath( - path.join("out", "src", "mongo", "languageServer.js") - ) - : ext.context.asAbsolutePath( - path.join("dist", "mongo-languageServer.bundle.js") - ); - // The debug options for the server - const debugOptions = { execArgv: ["--nolazy", "--inspect=6005"] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { - module: serverModule, - transport: TransportKind.ipc, - options: debugOptions, - }, - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: "mongo", scheme: "file" }, - { language: "mongo", scheme: "untitled" }, - ], - }; - - // Create the language client and start the client. - this.client = new LanguageClient( - "mongo", - localize("mongo.server.name", "Mongo Language Server"), - serverOptions, - clientOptions - ); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect( - connectionString: string, - databaseName: string - ): Promise { - await this.client.sendRequest("connect", { - connectionString: connectionString, - databaseName: databaseName, - extensionUserAgent: appendExtensionUserAgent(), - }); - } - - public async disconnect(): Promise { - await this.client.sendRequest("disconnect"); - } + public client: LanguageClient; + + constructor() { + // The server is implemented in node + const serverModule = ext.ignoreBundle ? + ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : + ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); + // The debug options for the server + const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; + + // If the extension is launch in debug mode the debug server options are use + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for mongo javascript documents + documentSelector: [ + { language: 'mongo', scheme: 'file' }, + { language: 'mongo', scheme: 'untitled' } + ] + }; + + // Create the language client and start the client. + this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); + const disposable = this.client.start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + ext.context.subscriptions.push(disposable); + } + + public async connect(connectionString: string, databaseName: string): Promise { + await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); + } + + public async disconnect(): Promise { + await this.client.sendRequest('disconnect'); + } } diff --git a/Source/mongo/languageServer.ts b/Source/mongo/languageServer.ts index 8c76686f6..d5d6ec484 100644 --- a/Source/mongo/languageServer.ts +++ b/Source/mongo/languageServer.ts @@ -2,8 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from "vscode-languageserver"; -import { LanguageService } from "./services/languageService"; +import { createConnection, IConnection } from 'vscode-languageserver'; +import { LanguageService } from './services/languageService'; // // diff --git a/Source/mongo/mongoConnectionStrings.ts b/Source/mongo/mongoConnectionStrings.ts index 89d04ed30..5f73db484 100644 --- a/Source/mongo/mongoConnectionStrings.ts +++ b/Source/mongo/mongoConnectionStrings.ts @@ -3,11 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - appendExtensionUserAgent, - IParsedError, - parseError, -} from "@microsoft/vscode-azext-utils"; +import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; import { MongoClient } from "mongodb"; import { testDb } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; @@ -25,118 +21,84 @@ import { connectToMongoClient } from "./connectToMongoClient"; // mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] // [database] -const parsePrefix = "([a-zA-Z]+://[^/]*)"; -const parseDatabaseName = "/?([^/?]+)?"; +const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; +const parseDatabaseName = '\/?([^/?]+)?'; const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); -export function getDatabaseNameFromConnectionString( - connectionString: string -): string | undefined { - try { - const [, , databaseName] = nonNullValue( - connectionString.match(mongoConnectionStringRegExp), - "databaseNameMatch" - ); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } +export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { + try { + const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); + return databaseName; + } catch (error) { + // Shouldn't happen, but ignore if does + } - return undefined; + return undefined; } -export function addDatabaseToAccountConnectionString( - connectionString: string, - databaseName: string -): string { - try { - return connectionString.replace( - mongoConnectionStringRegExp, - `$1\/${encodeURIComponent(databaseName)}` - ); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } +export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { + try { + return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); + } catch (error) { + // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it + return connectionString; + } } -export async function parseMongoConnectionString( - connectionString: string -): Promise { - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient( - connectionString, - appendExtensionUserAgent() - ); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient( - connectionString, - appendExtensionUserAgent() - ); - } else { - throw error; - } - } +export async function parseMongoConnectionString(connectionString: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; + let mongoClient: MongoClient; + try { + mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); + } catch (error) { + const parsedError: IParsedError = parseError(error); + if (parsedError.message.match(/unescaped/i)) { + // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 + connectionString = encodeMongoConnectionString(connectionString); + mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); + } else { + throw error; + } + } - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = - serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = - serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const serverConfig: any = mongoClient.db(testDb).serverConfig; - return new ParsedMongoConnectionString( - connectionString, - host, - port, - getDatabaseNameFromConnectionString(connectionString) - ); + // get the first connection string from the servers list + // this may not be best solution, but the connection (below) gives + // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) + // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; + + return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); } export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - constructor( - connectionString: string, - hostName: string, - port: string, - databaseName: string | undefined - ) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } + constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { + super(connectionString, databaseName); + this.hostName = hostName; + this.port = port; + } } /** * Encodes the username and password in the given Mongo DB connection string. */ export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match( - /^(.*):\/\/(.*):(.*)@(.*)/ - ); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent( - username - )}:${encodeURIComponent(password)}@${hostAndQuery}`; - } + const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); + if (matches) { + const prefix: string = matches[1]; + const username: string = matches[2]; + const password: string = matches[3]; + const hostAndQuery: string = matches[4]; + connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; + } - return connectionString; + return connectionString; } diff --git a/Source/mongo/registerMongoCommands.ts b/Source/mongo/registerMongoCommands.ts index 713ff9104..2dc36477a 100644 --- a/Source/mongo/registerMongoCommands.ts +++ b/Source/mongo/registerMongoCommands.ts @@ -3,28 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, - IErrorHandlerContext, - ITreeItemPickerContext, - registerCommandWithTreeNodeUnwrapping, - registerErrorHandler, - registerEvent, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { Experience, MongoExperience } from "../AzureDBExperiences"; +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; +import * as vscode from 'vscode'; +import { Experience, MongoExperience } from '../AzureDBExperiences'; import { cosmosMongoFilter } from "../constants"; import { ext } from "../extensionVariables"; -import * as vscodeUtil from "../utils/vscodeUtils"; -import { MongoConnectError } from "./connectToMongoClient"; +import * as vscodeUtil from '../utils/vscodeUtils'; +import { MongoConnectError } from './connectToMongoClient'; import { MongoDBLanguageClient } from "./languageClient"; -import { - executeAllCommandsFromActiveEditor, - executeCommandFromActiveEditor, - getAllErrorsFromTextDocument, -} from "./MongoScrapbook"; +import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; import { setConnectedNode } from "./setConnectedNode"; import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; @@ -32,328 +19,205 @@ import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; -const connectedMongoKey: string = "ms-azuretools.vscode-cosmosdb.connectedDB"; +const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = "mongo"; +const mongoLanguageId: string = 'mongo'; export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push( - vscode.languages.registerCodeLensProvider( - mongoLanguageId, - ext.mongoCodeLensProvider - ) - ); - - diagnosticsCollection = - vscode.languages.createDiagnosticCollection("cosmosDB.mongo"); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createMongoDatabase", - createMongoDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createMongoCollection", - createMongoCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createMongoDocument", - async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo( - context, - MongoCollectionTreeItem.contextValue - ); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand( - "cosmosDB.openDocument", - documentNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.connectMongoDB", - async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { - defaultExperience?: Experience; - } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo( - experienceContext, - MongoDatabaseTreeItem.contextValue - ); - } - - const oldNodeId: string | undefined = - ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect( - node.connectionString, - node.databaseName - ); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - oldNodeId, - context - ); - if (oldNode) { - await oldNode.refresh(context); - } - } - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteMongoDB", - deleteMongoDB - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteMongoCollection", - deleteMongoCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteMongoDocument", - async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo( - context, - MongoDocumentTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openCollection", - async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo( - context, - MongoCollectionTreeItem.contextValue - ); - } - await ext.fileSystem.showTextDocument(node); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.launchMongoShell", - launchMongoShell - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.newMongoScrapbook", - async () => await vscodeUtil.showNewFile("", "Scrapbook", ".mongo") - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.executeMongoCommand", - async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.executeAllMongoCommands", - async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - } - ); + ext.mongoLanguageClient = new MongoDBLanguageClient(); + + ext.mongoCodeLensProvider = new MongoCodeLensProvider(); + ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); + + diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); + ext.context.subscriptions.push(diagnosticsCollection); + + setUpErrorReporting(); + + const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); + + registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo(context, MongoCollectionTreeItem.contextValue); + } + const documentNode = await node.createChild(context); + await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { + if (!node) { + // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 + const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; + node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); + } + + const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; + await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); + void ext.context.globalState.update(connectedMongoKey, node.fullId); + setConnectedNode(node); + await node.refresh(context); + + if (oldNodeId) { + // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); + if (oldNode) { + await oldNode.refresh(context); + } + } + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo(context, MongoDocumentTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo(context, MongoCollectionTreeItem.contextValue); + } + await ext.fileSystem.showTextDocument(node); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); + registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); + registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { + await loadPersistedMongoDBTask; + await executeCommandFromActiveEditor(context, position); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { + await loadPersistedMongoDBTask; + await executeAllCommandsFromActiveEditor(context); + }); } async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling( - "cosmosDB.loadPersistedMongoDB", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = "true"; - - try { - const persistedNodeId: string | undefined = - ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = - await ext.rgApi.appResourceTree.findTreeItem( - persistedNodeId, - context - ); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand( - "cosmosDB.connectMongoDB", - persistedNode - ); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - } - ); + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = 'true'; + + try { + const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); + if (persistedNodeId) { + const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); + if (persistedNode) { + await ext.mongoLanguageClient.client.onReady(); + await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedMongoDB) { + ext.mongoCodeLensProvider.setConnectedDatabase(undefined); + } + } + }); } function launchMongoShell(): void { - const terminal: vscode.Terminal = - vscode.window.createTerminal("Mongo Shell"); - terminal.sendText(`mongo`); - terminal.show(); + const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); + terminal.sendText(`mongo`); + terminal.show(); } function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook( - context, - vscode.window.activeTextEditor?.document - ); - } - ); - - // Update errors when document opened/changed - registerEvent( - "vscode.workspace.onDidOpenTextDocument", - vscode.workspace.onDidOpenTextDocument, - updateErrorsInScrapbook - ); - registerEvent( - "vscode.workspace.onDidChangeTextDocument", - vscode.workspace.onDidChangeTextDocument, - async ( - context: IActionContext, - event: vscode.TextDocumentChangeEvent - ) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - } - ); - registerEvent( - "vscode.workspace.onDidCloseTextDocument", - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - } - ); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); + // Update errors immediately in case a scrapbook is already open + void callWithTelemetryAndErrorHandling( + "initialUpdateErrorsInActiveDocument", + async (context: IActionContext) => { + updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); + }); + + // Update errors when document opened/changed + registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); + registerEvent( + 'vscode.workspace.onDidChangeTextDocument', + vscode.workspace.onDidChangeTextDocument, + async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { + // Always suppress success telemetry - event happens on every keystroke + context.telemetry.suppressIfSuccessful = true; + + updateErrorsInScrapbook(context, event.document); + }); + registerEvent( + 'vscode.workspace.onDidCloseTextDocument', + vscode.workspace.onDidCloseTextDocument, + async (context: IActionContext, document: vscode.TextDocument) => { + // Remove errors when closed + if (document?.languageId === mongoLanguageId) { + diagnosticsCollection.set(document.uri, []); + } else { + context.telemetry.suppressIfSuccessful = true; + } + }); + + registerErrorHandler((context: IErrorHandlerContext) => { + if (context.error instanceof MongoConnectError) { + context.errorHandling.suppressReportIssue = true; + } + }); } -function updateErrorsInScrapbook( - context: IActionContext, - document: vscode.TextDocument | undefined -): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } +function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { + if (document?.languageId === mongoLanguageId) { + const errors = getAllErrorsFromTextDocument(document); + diagnosticsCollection.set(document.uri, errors); + } else { + context.telemetry.suppressIfSuccessful = true; + } } -export async function createMongoDatabase( - context: IActionContext, - node?: MongoAccountTreeItem -): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); +export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { + if (!node) { + node = await pickMongo(context); + } + const databaseNode = await node.createChild(context); + await databaseNode.createChild(context); - await vscode.commands.executeCommand( - "cosmosDB.connectMongoDB", - databaseNode - ); + await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); } -export async function createMongoCollection( - context: IActionContext, - node?: MongoDatabaseTreeItem -): Promise { - if (!node) { - node = await pickMongo( - context, - MongoDatabaseTreeItem.contextValue - ); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand( - "cosmosDB.connectMongoDB", - collectionNode.parent - ); +export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { + if (!node) { + node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); + } + const collectionNode = await node.createChild(context); + await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); } -export async function deleteMongoDB( - context: IActionContext, - node?: MongoDatabaseTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo( - context, - MongoDatabaseTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } +export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); + } + await node.deleteTreeItem(context); + if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { + setConnectedNode(undefined); + void ext.context.globalState.update(connectedMongoKey, undefined); + // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 + void ext.mongoLanguageClient.disconnect(); + } } -export async function deleteMongoCollection( - context: IActionContext, - node?: MongoCollectionTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo( - context, - MongoCollectionTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); +export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo(context, MongoCollectionTreeItem.contextValue); + } + await node.deleteTreeItem(context); } -async function pickMongo( - context: IActionContext, - expectedContextValue?: string | RegExp | (string | RegExp)[] -): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [cosmosMongoFilter], - expectedChildContextValue: expectedContextValue, - }); +async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter + ], + expectedChildContextValue: expectedContextValue + }); } diff --git a/Source/mongo/services/IConnectionParams.ts b/Source/mongo/services/IConnectionParams.ts index 55d2cc73a..eec39e4cf 100644 --- a/Source/mongo/services/IConnectionParams.ts +++ b/Source/mongo/services/IConnectionParams.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; + connectionString: string; + databaseName: string; + extensionUserAgent: string; } diff --git a/Source/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts index 01aaff56f..3407c50dd 100644 --- a/Source/mongo/services/MongoCodeLensProvider.ts +++ b/Source/mongo/services/MongoCodeLensProvider.ts @@ -3,89 +3,73 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = - new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): vscode.Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses( - document: vscode.TextDocument, - _token: vscode.CancellationToken - ): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling( - "mongo.provideCodeLenses", - (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { + return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: vscode.CodeLens[] = []; - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized - ? "Initializing..." - : isConnected - ? `Connected to ${database}` - : `Connect to a database`, - command: isInitialized && "cosmosDB.connectMongoDB", - }, - range: new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position(0, 0) - ), - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title: !isInitialized ? + 'Initializing...' : + isConnected ? + `Connected to ${database}` : + `Connect to a database`, + command: isInitialized && 'cosmosDB.connectMongoDB' + }, + range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) + }); - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: "cosmosDB.executeAllMongoCommands", - }, - range: new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position(0, 0) - ), - }); + if (isConnected) { + // Run all + lenses.push({ + command: { + title: "Execute All", + command: 'cosmosDB.executeAllMongoCommands' + }, + range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) + }); - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: "cosmosDB.executeMongoCommand", - arguments: [cmd.range.start], - }, - range: cmd.range, - }); - } - } + const commands = getAllCommandsFromTextDocument(document); + for (const cmd of commands) { + // run individual + lenses.push({ + command: { + title: "Execute", + command: 'cosmosDB.executeMongoCommand', + arguments: [cmd.range.start] + }, + range: cmd.range + }); + } + } - return lenses; - } - ); - } + return lenses; + }); + } } diff --git a/Source/mongo/services/completionItemProvider.ts b/Source/mongo/services/completionItemProvider.ts index 4abb71432..cba51890c 100644 --- a/Source/mongo/services/completionItemProvider.ts +++ b/Source/mongo/services/completionItemProvider.ts @@ -5,588 +5,435 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ErrorNode } from "antlr4ts/tree/ErrorNode"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Db } from "mongodb"; -import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; -import { - CompletionItem, - CompletionItemKind, - Position, - Range, -} from "vscode-languageserver"; -import { TextDocument } from "vscode-languageserver-textdocument"; -import { mongoLexer } from "./../grammar/mongoLexer"; -import * as mongoParser from "./../grammar/mongoParser"; -import { MongoVisitor } from "./../grammar/visitors"; -import { SchemaService } from "./schemaService"; - -export class CompletionItemsVisitor extends MongoVisitor< - Promise -> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands( - ctx: mongoParser.CommandsContext - ): Promise { - return this.thenable( - this.createDbKeywordCompletion(this.createRange(ctx)) - ); - } - - public visitEmptyCommand( - ctx: mongoParser.EmptyCommandContext - ): Promise { - return this.thenable( - this.createDbKeywordCompletion(this.createRangeAfter(ctx)) - ); - } - - public visitCommand( - ctx: mongoParser.CommandContext - ): Promise { - if (ctx.childCount === 0) { - return this.thenable( - this.createDbKeywordCompletion(this.createRange(ctx)) - ); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection( - ctx: mongoParser.CollectionContext - ): Promise { - return Promise.all([ - this.createCollectionCompletions(this.createRange(ctx)), - this.createDbFunctionCompletions(this.createRange(ctx)), - ]).then(([collectionCompletions, dbFunctionCompletions]) => [ - ...collectionCompletions, - ...dbFunctionCompletions, - ]); - } - - public visitFunctionCall( - ctx: mongoParser.FunctionCallContext - ): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments( - ctx: mongoParser.ArgumentsContext - ): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable( - this.createDbKeywordCompletion( - this.createRangeAfter(terminalNode) - ) - ); - } - return this.thenable(); - } - - public visitArgument( - ctx: mongoParser.ArgumentContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral( - ctx: mongoParser.ObjectLiteralContext - ): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if ( - [ - "find", - "findOne", - "findOneAndDelete", - "findOneAndUpdate", - "findOneAndReplace", - "deleteOne", - "deleteMany", - "remove", - ].indexOf(functionName) !== -1 - ) { - return this.getArgumentCompletionItems( - this.schemaService.queryDocumentUri(collectionName), - collectionName, - ctx - ); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral( - ctx: mongoParser.ArrayLiteralContext - ): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (["aggregate"].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems( - this.schemaService.aggregateDocumentUri(collectionName), - collectionName, - ctx - ); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList( - ctx: mongoParser.ElementListContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList( - ctx: mongoParser.PropertyNameAndValueListContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment( - ctx: mongoParser.PropertyAssignmentContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue( - ctx: mongoParser.PropertyValueContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName( - ctx: mongoParser.PropertyNameContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral( - ctx: mongoParser.LiteralContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems( - documentUri: string, - _collectionName: string, - ctx: ParserRuleContext - ): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create( - documentUri, - "json", - 1, - text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1) - ); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService - .doComplete( - document, - position, - this.jsonLanguageService.parseJSONDocument(document) - ) - .then((list) => { - return list!.items.map((item) => { - const startPositionOffset = document.offsetAt( - item.textEdit!.range.start - ); - const endPositionOffset = document.offsetAt( - item.textEdit!.range.end - ); - item.textEdit!.range = Range.create( - this.textDocument.positionAt( - startPositionOffset + contextOffset - ), - this.textDocument.positionAt( - contextOffset + endPositionOffset - ) - ); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if ( - previousNode && - previousNode instanceof TerminalNode && - previousNode.symbol.type === mongoLexer.DOT - ) { - previousNode = this.getPreviousNode(previousNode); - if ( - previousNode && - previousNode instanceof mongoParser.CollectionContext - ) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode( - node: TerminalNode - ): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable( - this.createDbKeywordCompletion(this.createRange(node)) - ); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable( - this.createDbKeywordCompletion(this.createRangeAfter(node)) - ); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([ - this.createCollectionCompletions( - this.createRangeAfter(node) - ), - this.createDbFunctionCompletions( - this.createRangeAfter(node) - ), - ]).then( - ([collectionCompletions, dbFunctionCompletions]) => [ - ...collectionCompletions, - ...dbFunctionCompletions, - ] - ); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions( - this.createRangeAfter(node) - ); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode( - previousNode - ); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children - .slice() - .reverse() - .filter( - (node) => - node instanceof TerminalNode && - node.symbol.stopIndex > -1 && - node.symbol.stopIndex < this.offset - )[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: "db", - range, - }, - kind: CompletionItemKind.Keyword, - label: "db", - }; - } - - private createDbFunctionCompletions( - range: Range - ): Promise { - return this.thenable( - this.createFunctionCompletion("adminCommand", range), - this.createFunctionCompletion("auth", range), - this.createFunctionCompletion("cloneDatabase", range), - this.createFunctionCompletion("commandHelp", range), - this.createFunctionCompletion("copyDatabase", range), - this.createFunctionCompletion("createCollection", range), - this.createFunctionCompletion("createView", range), - this.createFunctionCompletion("createUser", range), - this.createFunctionCompletion("currentOp", range), - this.createFunctionCompletion("dropDatabase", range), - this.createFunctionCompletion("eval", range), - this.createFunctionCompletion("fsyncLock", range), - this.createFunctionCompletion("fsyncUnLock", range), - this.createFunctionCompletion("getCollection", range), - this.createFunctionCompletion("getCollectionInfos", range), - this.createFunctionCompletion("getCollectionNames", range), - this.createFunctionCompletion("getLastError", range), - this.createFunctionCompletion("getLastErrorObj", range), - this.createFunctionCompletion("getLogComponents", range), - this.createFunctionCompletion("getMongo", range), - this.createFunctionCompletion("getName", range), - this.createFunctionCompletion("getPrevError", range), - this.createFunctionCompletion("getProfilingLevel", range), - this.createFunctionCompletion("getProfilingStatus", range), - this.createFunctionCompletion("getReplicationInfo", range), - this.createFunctionCompletion("getSiblingDB", range), - this.createFunctionCompletion("getWriteConcern", range), - this.createFunctionCompletion("hostInfo", range), - this.createFunctionCompletion("isMaster", range), - this.createFunctionCompletion("killOp", range), - this.createFunctionCompletion("listCommands", range), - this.createFunctionCompletion("loadServerScripts", range), - this.createFunctionCompletion("logout", range), - this.createFunctionCompletion("printCollectionStats", range), - this.createFunctionCompletion("printReplicationInfo", range), - this.createFunctionCompletion("printShardingStatus", range), - this.createFunctionCompletion("printSlaveReplicationInfo", range), - this.createFunctionCompletion("dropUser", range), - this.createFunctionCompletion("repairDatabase", range), - this.createFunctionCompletion("runCommand", range), - this.createFunctionCompletion("serverStatus", range), - this.createFunctionCompletion("setLogLevel", range), - this.createFunctionCompletion("setProfilingLevel", range), - this.createFunctionCompletion("setWriteConcern", range), - this.createFunctionCompletion("unsetWriteConcern", range), - this.createFunctionCompletion("setVerboseShell", range), - this.createFunctionCompletion("shotdownServer", range), - this.createFunctionCompletion("stats", range), - this.createFunctionCompletion("version", range) - ); - } - - private createCollectionCompletions( - range: Range - ): Promise { - if (this.db) { - return >( - this.db.collections().then((collections) => { - return collections.map( - (collection) => - { - textEdit: { - newText: collection.collectionName, - range, - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}`, - } - ); - }) - ); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions( - range: Range - ): Promise { - return this.thenable( - this.createFunctionCompletion("bulkWrite", range), - this.createFunctionCompletion("count", range), - this.createFunctionCompletion("copyTo", range), - this.createFunctionCompletion("convertToCapped", range), - this.createFunctionCompletion("createIndex", range), - this.createFunctionCompletion("createIndexes", range), - this.createFunctionCompletion("dataSize", range), - this.createFunctionCompletion("deleteOne", range), - this.createFunctionCompletion("deleteMany", range), - this.createFunctionCompletion("distinct", range), - this.createFunctionCompletion("drop", range), - this.createFunctionCompletion("dropIndex", range), - this.createFunctionCompletion("dropIndexes", range), - this.createFunctionCompletion("ensureIndex", range), - this.createFunctionCompletion("explain", range), - this.createFunctionCompletion("reIndex", range), - this.createFunctionCompletion("find", range), - this.createFunctionCompletion("findOne", range), - this.createFunctionCompletion("findOneAndDelete", range), - this.createFunctionCompletion("findOneAndReplace", range), - this.createFunctionCompletion("findOneAndUpdate", range), - this.createFunctionCompletion("getDB", range), - this.createFunctionCompletion("getPlanCache", range), - this.createFunctionCompletion("getIndexes", range), - this.createFunctionCompletion("group", range), - this.createFunctionCompletion("insert", range), - this.createFunctionCompletion("insertOne", range), - this.createFunctionCompletion("insertMany", range), - this.createFunctionCompletion("mapReduce", range), - this.createFunctionCompletion("aggregate", range), - this.createFunctionCompletion("remove", range), - this.createFunctionCompletion("replaceOne", range), - this.createFunctionCompletion("renameCollection", range), - this.createFunctionCompletion("runCommand", range), - this.createFunctionCompletion("save", range), - this.createFunctionCompletion("stats", range), - this.createFunctionCompletion("storageSize", range), - this.createFunctionCompletion("totalIndexSize", range), - this.createFunctionCompletion("update", range), - this.createFunctionCompletion("updateOne", range), - this.createFunctionCompletion("updateMany", range), - this.createFunctionCompletion("validate", range), - this.createFunctionCompletion("getShardVersion", range), - this.createFunctionCompletion("getShardDistribution", range), - this.createFunctionCompletion("getSplitKeysForChunks", range), - this.createFunctionCompletion("getWriteConcern", range), - this.createFunctionCompletion("setWriteConcern", range), - this.createFunctionCompletion("unsetWriteConcern", range), - this.createFunctionCompletion("latencyStats", range) - ); - } - - private createFunctionCompletion( - label: string, - range: Range - ): CompletionItem { - return { - textEdit: { - newText: label, - range, - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}`, - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange( - parserRuleContext.symbol.startIndex, - parserRuleContext.symbol.stopIndex - ); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange( - parserRuleContext.symbol.stopIndex + 1, - parserRuleContext.symbol.stopIndex + 1 - ); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable( - ...completionItems: CompletionItem[] - ): Promise { - return Promise.resolve(completionItems || []); - } +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { Db } from 'mongodb'; +import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; +import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { mongoLexer } from './../grammar/mongoLexer'; +import * as mongoParser from './../grammar/mongoParser'; +import { MongoVisitor } from './../grammar/visitors'; +import { SchemaService } from './schemaService'; + +export class CompletionItemsVisitor extends MongoVisitor> { + private at: Position; + + constructor( + private textDocument: TextDocument, + private db: Db, + private offset: number, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + super(); + this.at = this.textDocument.positionAt(this.offset); + } + + public visitCommands(ctx: mongoParser.CommandsContext): Promise { + return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); + } + + public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { + return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); + } + + public visitCommand(ctx: mongoParser.CommandContext): Promise { + if (ctx.childCount === 0) { + return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); + } + + const lastTerminalNode = this.getLastTerminalNode(ctx); + if (lastTerminalNode) { + return this.getCompletionItemsFromTerminalNode(lastTerminalNode); + } + return this.thenable(); + } + + public visitCollection(ctx: mongoParser.CollectionContext): Promise { + return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) + .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); + } + + public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { + const previousNode = this.getPreviousNode(ctx); + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return this.thenable(); + } + + public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { + const terminalNode = this.getLastTerminalNode(ctx); + if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { + return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); + } + return this.thenable(); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): Promise { + return ctx.parent!.accept(this); + } + + public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); + } + } + return ctx.parent!.accept(this); + } + + public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (['aggregate'].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); + } + } + return ctx.parent!.accept(this); + } + + public visitElementList(ctx: mongoParser.ElementListContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { + return ctx.parent!.accept(this); + } + + public visitLiteral(ctx: mongoParser.LiteralContext): Promise { + return ctx.parent!.accept(this); + } + + public visitTerminal(ctx: TerminalNode): Promise { + return ctx.parent!.accept(this); + } + + public visitErrorNode(ctx: ErrorNode): Promise { + return ctx.parent!.accept(this); + } + + private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { + const text = this.textDocument.getText(); + const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); + const positionOffset = this.textDocument.offsetAt(this.at); + const contextOffset = ctx.start.startIndex; + const position = document.positionAt(positionOffset - contextOffset); + return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) + .then(list => { + return list!.items.map(item => { + const startPositionOffset = document.offsetAt(item.textEdit!.range.start); + const endPositionOffset = document.offsetAt(item.textEdit!.range.end); + item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); + return item; + }); + }); + } + + private getFunctionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + return (parent)._FUNCTION_NAME.text!; + } + + private getCollectionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + let previousNode = this.getPreviousNode(parent); + if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { + previousNode = this.getPreviousNode(previousNode); + if (previousNode && previousNode instanceof mongoParser.CollectionContext) { + return previousNode.text; + } + } + return null!; + } + + private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { + if (node._symbol.type === mongoParser.mongoParser.DB) { + return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); + } + if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { + return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); + } + if (node._symbol.type === mongoParser.mongoParser.DOT) { + const previousNode = this.getPreviousNode(node); + if (previousNode && previousNode instanceof TerminalNode) { + if (previousNode._symbol.type === mongoParser.mongoParser.DB) { + return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) + .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); + } + } + if (previousNode instanceof mongoParser.CollectionContext) { + return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); + } + } + if (node instanceof ErrorNode) { + const previousNode = this.getPreviousNode(node); + if (previousNode) { + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return previousNode.accept(this); + } + } + return this.thenable(); + } + + private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { + return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; + } + + private getPreviousNode(node: ParseTree): ParseTree { + let previousNode: ParseTree = null!; + const parentNode = node.parent!; + for (let i = 0; i < parentNode.childCount; i++) { + const currentNode = parentNode.getChild(i); + if (currentNode === node) { + break; + } + previousNode = currentNode; + } + return previousNode; + } + + private createDbKeywordCompletion(range: Range): CompletionItem { + return { + textEdit: { + newText: 'db', + range + }, + kind: CompletionItemKind.Keyword, + label: 'db' + }; + } + + private createDbFunctionCompletions(range: Range): Promise { + return this.thenable( + this.createFunctionCompletion('adminCommand', range), + this.createFunctionCompletion('auth', range), + this.createFunctionCompletion('cloneDatabase', range), + this.createFunctionCompletion('commandHelp', range), + this.createFunctionCompletion('copyDatabase', range), + this.createFunctionCompletion('createCollection', range), + this.createFunctionCompletion('createView', range), + this.createFunctionCompletion('createUser', range), + this.createFunctionCompletion('currentOp', range), + this.createFunctionCompletion('dropDatabase', range), + this.createFunctionCompletion('eval', range), + this.createFunctionCompletion('fsyncLock', range), + this.createFunctionCompletion('fsyncUnLock', range), + this.createFunctionCompletion('getCollection', range), + this.createFunctionCompletion('getCollectionInfos', range), + this.createFunctionCompletion('getCollectionNames', range), + this.createFunctionCompletion('getLastError', range), + this.createFunctionCompletion('getLastErrorObj', range), + this.createFunctionCompletion('getLogComponents', range), + this.createFunctionCompletion('getMongo', range), + this.createFunctionCompletion('getName', range), + this.createFunctionCompletion('getPrevError', range), + this.createFunctionCompletion('getProfilingLevel', range), + this.createFunctionCompletion('getProfilingStatus', range), + this.createFunctionCompletion('getReplicationInfo', range), + this.createFunctionCompletion('getSiblingDB', range), + this.createFunctionCompletion('getWriteConcern', range), + this.createFunctionCompletion('hostInfo', range), + this.createFunctionCompletion('isMaster', range), + this.createFunctionCompletion('killOp', range), + this.createFunctionCompletion('listCommands', range), + this.createFunctionCompletion('loadServerScripts', range), + this.createFunctionCompletion('logout', range), + this.createFunctionCompletion('printCollectionStats', range), + this.createFunctionCompletion('printReplicationInfo', range), + this.createFunctionCompletion('printShardingStatus', range), + this.createFunctionCompletion('printSlaveReplicationInfo', range), + this.createFunctionCompletion('dropUser', range), + this.createFunctionCompletion('repairDatabase', range), + this.createFunctionCompletion('runCommand', range), + this.createFunctionCompletion('serverStatus', range), + this.createFunctionCompletion('setLogLevel', range), + this.createFunctionCompletion('setProfilingLevel', range), + this.createFunctionCompletion('setWriteConcern', range), + this.createFunctionCompletion('unsetWriteConcern', range), + this.createFunctionCompletion('setVerboseShell', range), + this.createFunctionCompletion('shotdownServer', range), + this.createFunctionCompletion('stats', range), + this.createFunctionCompletion('version', range) + ); + } + + private createCollectionCompletions(range: Range): Promise { + if (this.db) { + return >this.db.collections().then(collections => { + return collections.map(collection => ({ + textEdit: { + newText: collection.collectionName, + range + }, + label: collection.collectionName, + kind: CompletionItemKind.Property, + filterText: collection.collectionName, + sortText: `1:${collection.collectionName}` + })); + }); + } + return Promise.resolve([]); + } + + private createCollectionFunctionsCompletions(range: Range): Promise { + return this.thenable( + this.createFunctionCompletion('bulkWrite', range), + this.createFunctionCompletion('count', range), + this.createFunctionCompletion('copyTo', range), + this.createFunctionCompletion('convertToCapped', range), + this.createFunctionCompletion('createIndex', range), + this.createFunctionCompletion('createIndexes', range), + this.createFunctionCompletion('dataSize', range), + this.createFunctionCompletion('deleteOne', range), + this.createFunctionCompletion('deleteMany', range), + this.createFunctionCompletion('distinct', range), + this.createFunctionCompletion('drop', range), + this.createFunctionCompletion('dropIndex', range), + this.createFunctionCompletion('dropIndexes', range), + this.createFunctionCompletion('ensureIndex', range), + this.createFunctionCompletion('explain', range), + this.createFunctionCompletion('reIndex', range), + this.createFunctionCompletion('find', range), + this.createFunctionCompletion('findOne', range), + this.createFunctionCompletion('findOneAndDelete', range), + this.createFunctionCompletion('findOneAndReplace', range), + this.createFunctionCompletion('findOneAndUpdate', range), + this.createFunctionCompletion('getDB', range), + this.createFunctionCompletion('getPlanCache', range), + this.createFunctionCompletion('getIndexes', range), + this.createFunctionCompletion('group', range), + this.createFunctionCompletion('insert', range), + this.createFunctionCompletion('insertOne', range), + this.createFunctionCompletion('insertMany', range), + this.createFunctionCompletion('mapReduce', range), + this.createFunctionCompletion('aggregate', range), + this.createFunctionCompletion('remove', range), + this.createFunctionCompletion('replaceOne', range), + this.createFunctionCompletion('renameCollection', range), + this.createFunctionCompletion('runCommand', range), + this.createFunctionCompletion('save', range), + this.createFunctionCompletion('stats', range), + this.createFunctionCompletion('storageSize', range), + this.createFunctionCompletion('totalIndexSize', range), + this.createFunctionCompletion('update', range), + this.createFunctionCompletion('updateOne', range), + this.createFunctionCompletion('updateMany', range), + this.createFunctionCompletion('validate', range), + this.createFunctionCompletion('getShardVersion', range), + this.createFunctionCompletion('getShardDistribution', range), + this.createFunctionCompletion('getSplitKeysForChunks', range), + this.createFunctionCompletion('getWriteConcern', range), + this.createFunctionCompletion('setWriteConcern', range), + this.createFunctionCompletion('unsetWriteConcern', range), + this.createFunctionCompletion('latencyStats', range) + ); + } + + private createFunctionCompletion(label: string, range: Range): CompletionItem { + return { + textEdit: { + newText: label, + range + }, + kind: CompletionItemKind.Function, + label, + sortText: `2:${label}` + }; + } + + private createRange(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + const startToken = parserRuleContext.start; + let stopToken = parserRuleContext.stop; + if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { + stopToken = startToken; + } + + const stop = stopToken.stopIndex; + return this._createRange(startToken.startIndex, stop); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); + } + + return null!; + } + + private createRangeAfter(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + let stopToken = parserRuleContext.stop; + if (!stopToken) { + stopToken = parserRuleContext.start; + } + + const stop = stopToken.stopIndex; + return this._createRange(stop + 1, stop + 1); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); + } + + //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want + // to introduce a regression bug. + return null!; + } + + private _createRange(start: number, end: number): Range { + const endPosition = this.textDocument.positionAt(end); + if (endPosition.line < this.at.line) { + return Range.create(Position.create(this.at.line, 0), this.at); + } + const startPosition = this.textDocument.positionAt(start); + return Range.create(startPosition, endPosition); + } + + private thenable(...completionItems: CompletionItem[]): Promise { + return Promise.resolve(completionItems || []); + } + } diff --git a/Source/mongo/services/languageService.ts b/Source/mongo/services/languageService.ts index 7629c9258..83b1b594e 100644 --- a/Source/mongo/services/languageService.ts +++ b/Source/mongo/services/languageService.ts @@ -5,119 +5,86 @@ // NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) -import { Db } from "mongodb"; -import { - getLanguageService, - LanguageService as JsonLanguageService, - SchemaConfiguration, -} from "vscode-json-languageservice"; -import { - CompletionItem, - IConnection, - InitializeParams, - InitializeResult, - TextDocumentPositionParams, - TextDocuments, - TextDocumentSyncKind, -} from "vscode-languageserver"; -import { TextDocument } from "vscode-languageserver-textdocument"; -import { connectToMongoClient } from "../connectToMongoClient"; -import { IConnectionParams } from "./IConnectionParams"; -import { MongoScriptDocumentManager } from "./mongoScript"; -import { SchemaService } from "./schemaService"; +import { Db } from 'mongodb'; +import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; +import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { connectToMongoClient } from '../connectToMongoClient'; +import { IConnectionParams } from './IConnectionParams'; +import { MongoScriptDocumentManager } from './mongoScript'; +import { SchemaService } from './schemaService'; export class LanguageService { - private textDocuments: TextDocuments = new TextDocuments( - TextDocument - ); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize( - (_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ["."] }, - }, - }; - } - ); - - connection.onCompletion((textDocumentPosition) => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest( - "connect", - (connectionParams: IConnectionParams) => { - void connectToMongoClient( - connectionParams.connectionString, - connectionParams.extensionUserAgent - ).then((account) => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService - .registerSchemas(this.db) - .then((schemas) => { - this.configureSchemas(schemas); - }); - }); - } - ); - - connection.onRequest("disconnect", () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: (uri) => - this.schemaService.resolveSchema(uri), - contributions: [], - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager( - this.schemaService, - this.jsonLanguageService - ); - } - - public provideCompletionItems( - positionParams: TextDocumentPositionParams - ): Promise { - const textDocument = this.textDocuments.get( - positionParams.textDocument.uri - ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument( - textDocument!, - this.db - ); - return mongoScriptDocument.provideCompletionItemsAt( - positionParams.position - ); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas, - }); - } + + private textDocuments: TextDocuments = new TextDocuments(TextDocument); + private readonly mongoDocumentsManager: MongoScriptDocumentManager; + private db: Db; + + private jsonLanguageService: JsonLanguageService; + private schemaService: SchemaService; + private schemas: SchemaConfiguration[]; + + constructor(connection: IConnection) { + + this.schemaService = new SchemaService(); + + this.textDocuments.listen(connection); + // After the server has started the client sends an initilize request. The server receives + // in the passed params the rootPath of the workspace plus the client capabilities. + connection.onInitialize((_params: InitializeParams): InitializeResult => { + return { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode + completionProvider: { triggerCharacters: ['.'] } + } + }; + }); + + connection.onCompletion(textDocumentPosition => { + return this.provideCompletionItems(textDocumentPosition); + }); + + connection.onRequest('connect', (connectionParams: IConnectionParams) => { + void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) + .then(account => { + this.db = account.db(connectionParams.databaseName); + void this.schemaService.registerSchemas(this.db) + .then(schemas => { + this.configureSchemas(schemas); + }); + }); + }); + + connection.onRequest('disconnect', () => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.db = null!; + for (const schema of this.schemas) { + this.jsonLanguageService.resetSchema(schema.uri); + } + }); + + this.jsonLanguageService = getLanguageService({ + schemaRequestService: uri => this.schemaService.resolveSchema(uri), + contributions: [] + }); + + this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); + } + + public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { + const textDocument = this.textDocuments.get(positionParams.textDocument.uri); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); + return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); + } + + public resetSchema(uri: string): void { + this.jsonLanguageService.resetSchema(uri); + } + + public configureSchemas(schemas: SchemaConfiguration[]): void { + this.jsonLanguageService.configure({ + schemas + }); + } } diff --git a/Source/mongo/services/mongoScript.ts b/Source/mongo/services/mongoScript.ts index 4d5cb89dd..8d4c85398 100644 --- a/Source/mongo/services/mongoScript.ts +++ b/Source/mongo/services/mongoScript.ts @@ -2,133 +2,100 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; -import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; -import { Interval } from "antlr4ts/misc/Interval"; -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Db } from "mongodb"; -import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; -import { CompletionItem, Position } from "vscode-languageserver"; -import { TextDocument } from "vscode-languageserver-textdocument"; -import { mongoLexer } from "./../grammar/mongoLexer"; -import * as mongoParser from "./../grammar/mongoParser"; -import { MongoVisitor } from "./../grammar/visitors"; -import { CompletionItemsVisitor } from "./completionItemProvider"; -import { SchemaService } from "./schemaService"; +import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; +import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; +import { Interval } from 'antlr4ts/misc/Interval'; +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { Db } from 'mongodb'; +import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; +import { CompletionItem, Position } from 'vscode-languageserver'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { mongoLexer } from './../grammar/mongoLexer'; +import * as mongoParser from './../grammar/mongoParser'; +import { MongoVisitor } from './../grammar/visitors'; +import { CompletionItemsVisitor } from './completionItemProvider'; +import { SchemaService } from './schemaService'; export class MongoScriptDocumentManager { - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) {} - public getDocument( - textDocument: TextDocument, - db: Db - ): MongoScriptDocument { - return new MongoScriptDocument( - textDocument, - db, - this.schemaService, - this.jsonLanguageService - ); - } + constructor( + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + } + + public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { + return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); + } } export class MongoScriptDocument { - private readonly _lexer: mongoLexer; - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } + private readonly _lexer: mongoLexer; + + constructor( + private textDocument: TextDocument, + private db: Db, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + this._lexer = new mongoLexer(new InputStream(textDocument.getText())); + this._lexer.removeErrorListeners(); + } - public provideCompletionItemsAt( - position: Position - ): Promise { - const parser = new mongoParser.mongoParser( - new CommonTokenStream(this._lexer) - ); - parser.removeErrorListeners(); + public provideCompletionItemsAt(position: Position): Promise { + const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); + parser.removeErrorListeners(); - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor( - this.textDocument, - this.db, - offset, - this.schemaService, - this.jsonLanguageService - ).visit(lastNode); - } - return Promise.resolve([]); - } + const offset = this.textDocument.offsetAt(position); + const lastNode = new NodeFinder(offset).visit(parser.commands()); + if (lastNode) { + return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); + } + return Promise.resolve([]); + } } class NodeFinder extends MongoVisitor { - constructor(private offset: number) { - super(); - } - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } + constructor(private offset: number) { + super(); + } + + protected defaultResult(ctx: ParseTree): ParseTree { + if (ctx instanceof ParserRuleContext) { + const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; + if (stop < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + if (ctx instanceof TerminalNode) { + if (ctx.symbol.stopIndex < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } - protected aggregateResult( - aggregate: ParseTree, - nextResult: ParseTree - ): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = - aggregate instanceof ParserRuleContext - ? aggregate.start.startIndex - : (aggregate).symbol.startIndex; - const aggregateStop = - aggregate instanceof ParserRuleContext - ? aggregate.start.stopIndex - : (aggregate).symbol.stopIndex; - const nextResultStart = - nextResult instanceof ParserRuleContext - ? nextResult.start.startIndex - : (nextResult).symbol.startIndex; - const nextResultStop = - nextResult instanceof ParserRuleContext - ? nextResult.start.stopIndex - : (nextResult).symbol.stopIndex; + protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { + if (aggregate && nextResult) { + const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; + const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; + const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; + const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; - if ( - Interval.of(aggregateStart, aggregateStop).properlyContains( - Interval.of(nextResultStart, nextResultStop) - ) - ) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } + if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { + return aggregate; + } + return nextResult; + } + return nextResult ? nextResult : aggregate; + } } diff --git a/Source/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts index acb195725..cf70e8cde 100644 --- a/Source/mongo/services/schemaService.ts +++ b/Source/mongo/services/schemaService.ts @@ -5,726 +5,624 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ -import { Cursor, Db } from "mongodb"; -import { SchemaConfiguration } from "vscode-json-languageservice"; +import { Cursor, Db } from 'mongodb'; +import { SchemaConfiguration } from 'vscode-json-languageservice'; // eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from "vscode-json-languageservice/lib/umd/jsonSchema"; +import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; export class SchemaService { - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections().then((collections) => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push( - ...[ - { - uri: this.queryCollectionSchema( - collection.collectionName - ), - fileMatch: [ - this.queryDocumentUri( - collection.collectionName - ), - ], - }, - { - uri: this.aggregateCollectionSchema( - collection.collectionName - ), - fileMatch: [ - this.aggregateDocumentUri( - collection.collectionName - ), - ], - }, - ] - ); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return "mongo://query/" + collectionName + ".schema"; - } - - public aggregateCollectionSchema(collectionName: string): string { - return "mongo://aggregate/" + collectionName + ".schema"; - } - - public queryDocumentUri(collectionName: string): string { - return "mongo://query/" + collectionName + ".json"; - } - - public aggregateDocumentUri(collectionName: string): string { - return "mongo://aggregate/" + collectionName + ".json"; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith("mongo://query/")) { - return this._resolveQueryCollectionSchema( - uri.substring( - "mongo://query/".length, - uri.length - ".schema".length - ), - uri - ).then((sch) => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith("mongo://aggregate/")) { - return this._resolveAggregateCollectionSchema( - uri.substring( - "mongo://aggregate/".length, - uri.length - ".schema".length - ) - ).then((sch) => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(""); - } - - private _resolveQueryCollectionSchema( - collectionName: string, - schemaUri: string - ): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: "object", - properties: {}, - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema( - collectionName: string - ): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: "array", - items: this.getAggregateStagePropertiesSchema( - this.queryCollectionSchema(collectionName) - ), - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) - ? "array" - : document === null - ? "null" - : typeof document; - } - - private setSchemaForDocument( - parent: string, - document: any, - schema: JSONSchema - ): void { - if (this.getMongoDocumentType(document) === "object") { - for (const property of Object.keys(document)) { - if (!parent && ["_id"].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty( - parent, - property, - document, - schema - ); - } - } - } - - private setSchemaForDocumentProperty( - parent: string, - property: string, - document: any, - schema: JSONSchema - ): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, "object"], - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === "object") { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === "array") { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: "object", - description: "Performs text search", - properties: { - $search: { - type: "string", - description: - "A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase", - }, - $language: { - type: "string", - description: - 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming', - }, - $caseSensitive: { - type: "boolean", - description: - "Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index", - }, - $diacriticSensitive: { - type: "boolean", - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`, - }, - }, - required: ["$search"], - }; - - schema.properties!.$where = { - type: "string", - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`, - }; - schema.properties!.$comment = { - type: "string", - description: "Adds a comment to a query predicate", - }; - } - - private setLogicalOperatorProperties( - schema: JSONSchema, - schemaUri: string - ): void { - schema.properties!.$or = { - type: "array", - description: - "Joins query clauses with a logical OR returns all documents that match the conditions of either clause", - items: { - $ref: schemaUri, - }, - }; - schema.properties!.$and = { - type: "array", - description: - "Joins query clauses with a logical AND returns all documents that match the conditions of both clauses", - items: { - $ref: schemaUri, - }, - }; - schema.properties!.$nor = { - type: "array", - description: - "Joins query clauses with a logical NOR returns all documents that fail to match both clauses", - items: { - $ref: schemaUri, - }, - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {}, - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: "Matches values that are equal to a specified value", - }; - expressionSchema.properties.$gt = { - type: type, - description: - "Matches values that are greater than a specified value", - }; - expressionSchema.properties.$gte = { - type: type, - description: - "Matches values that are greater than or equal to a specified value", - }; - expressionSchema.properties.$lt = { - type: type, - description: "Matches values that are less than a specified value", - }; - expressionSchema.properties.$lte = { - type: type, - description: - "Matches values that are less than or equal to a specified value", - }; - expressionSchema.properties.$ne = { - type: type, - description: - "Matches all values that are not equal to a specified value", - }; - expressionSchema.properties.$in = { - type: "array", - description: "Matches any of the values specified in an array", - }; - expressionSchema.properties.$nin = { - type: "array", - description: "Matches none of the values specified in an array", - }; - - // Element operators - expressionSchema.properties.$exists = { - type: "boolean", - description: "Matches documents that have the specified field", - }; - expressionSchema.properties.$type = { - type: "string", - description: - "Selects documents if a field is of the specified type", - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: "array", - description: - "Performs a modulo operation on the value of a field and selects documents with a specified result", - maxItems: 2, - default: [2, 0], - }; - expressionSchema.properties.$regex = { - type: "string", - description: - "Selects documents where values match a specified regular expression", - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: "object", - properties: { - type: { - type: "string", - default: "GeoJSON object type", - }, - coordinates: { - type: "array", - }, - crs: { - type: "object", - properties: { - type: { - type: "string", - }, - properties: { - type: "object", - }, - }, - }, - }, - }; - expressionSchema.properties.$geoWithin = { - type: "object", - description: - "Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin", - properties: { - $geometry: geometryPropertySchema, - $box: { - type: "array", - }, - $polygon: { - type: "array", - }, - $center: { - type: "array", - }, - $centerSphere: { - type: "array", - }, - }, - }; - expressionSchema.properties.$geoIntersects = { - type: "object", - description: - "Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects", - properties: { - $geometry: geometryPropertySchema, - }, - }; - expressionSchema.properties.$near = { - type: "object", - description: - "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: "number", - }, - $minDistance: { - type: "number", - }, - }, - }; - expressionSchema.properties.$nearSphere = { - type: "object", - description: - "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: "number", - }, - $minDistance: { - type: "number", - }, - }, - }; - - // Array operatos - if (type === "array") { - expressionSchema.properties.$all = { - type: "array", - description: - "Matches arrays that contain all elements specified in the query", - }; - expressionSchema.properties.$size = { - type: "number", - description: - "Selects documents if the array field is a specified size", - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: "array", - description: - "Matches numeric or binary values in which a set of bit positions all have a value of 1", - }; - expressionSchema.properties.$bitsAnySet = { - type: "array", - description: - "Matches numeric or binary values in which any bit from a set of bit positions has a value of 1", - }; - expressionSchema.properties.$bitsAllClear = { - type: "array", - description: - "Matches numeric or binary values in which a set of bit positions all have a value of 0", - }; - expressionSchema.properties.$bitsAnyClear = { - type: "array", - description: - "Matches numeric or binary values in which any bit from a set of bit positions has a value of 0", - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: "object", - description: - "Inverts the effect of a query expression and returns documents that do not match the query expression", - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties }, - }; - schema.properties!.$elemMatch = { - type: "object", - }; - } - - private getAggregateStagePropertiesSchema( - querySchemaUri: string - ): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: "object", - properties: { - $collStats: { - type: "object", - description: - "Returns statistics regarding a collection or view", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $project: { - type: "object", - description: - "Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $match: { - type: "object", - description: - "Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)", - $ref: querySchemaUri, - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $redact: { - type: "object", - description: - "Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $limit: { - type: "object", - description: - "Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $skip: { - type: "object", - description: - "Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $unwind: { - type: "object", - description: - "Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $group: { - type: "object", - description: - "Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.", - properties: { - _id: { - type: ["string", "object"], - }, - }, - additionalProperties: { - type: "object", - }, - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $sample: { - type: "object", - description: - "Randomly selects the specified number of documents from its input", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $sort: { - type: "object", - description: - "Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $geoNear: { - type: "object", - description: - "Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $lookup: { - type: "object", - description: - "Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $out: { - type: "object", - description: - "Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $indexStats: { - type: "object", - description: - "Returns statistics regarding the use of each index for the collection", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $facet: { - type: "object", - description: - "Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $bucket: { - type: "object", - description: - "Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $bucketAuto: { - type: "object", - description: - "Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $sortByCount: { - type: "object", - description: - "Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $addFields: { - type: "object", - description: - "Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $replaceRoot: { - type: "object", - description: - "Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $count: { - type: "object", - description: - "Returns a count of the number of documents at this stage of the aggregation pipeline", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $graphLookup: { - type: "object", - description: - "Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document", - }, - }, - }); - return { - type: "object", - oneOf: schemas, - }; - } - - private readNext( - result: any[], - cursor: Cursor, - batchSize: number, - callback: (result: any[]) => void - ): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then((hasNext) => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then((doc) => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } + + private _db: Db; + private _schemasCache: Map = new Map(); + + public registerSchemas(db: Db): Thenable { + this._db = db; + this._schemasCache.clear(); + return this._db.collections() + .then(collections => { + const schemas: SchemaConfiguration[] = []; + for (const collection of collections) { + schemas.push(...[{ + uri: this.queryCollectionSchema(collection.collectionName), + fileMatch: [this.queryDocumentUri(collection.collectionName)] + }, { + uri: this.aggregateCollectionSchema(collection.collectionName), + fileMatch: [this.aggregateDocumentUri(collection.collectionName)] + }]); + } + return schemas; + }); + } + + public queryCollectionSchema(collectionName: string): string { + return 'mongo://query/' + collectionName + '.schema'; + } + + public aggregateCollectionSchema(collectionName: string): string { + return 'mongo://aggregate/' + collectionName + '.schema'; + } + + public queryDocumentUri(collectionName: string): string { + return 'mongo://query/' + collectionName + '.json'; + } + + public aggregateDocumentUri(collectionName: string): string { + return 'mongo://aggregate/' + collectionName + '.json'; + } + + public resolveSchema(uri: string): Thenable { + const schema = this._schemasCache.get(uri); + if (schema) { + return Promise.resolve(schema); + } + if (uri.startsWith('mongo://query/')) { + return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) + .then(sch => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + if (uri.startsWith('mongo://aggregate/')) { + return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) + .then(sch => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + return Promise.resolve(''); + } + + private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (result) => { + const schema: JSONSchema = { + type: 'object', + properties: {} + }; + for (const document of result) { + this.setSchemaForDocument(null!, document, schema); + } + this.setGlobalOperatorProperties(schema); + this.setLogicalOperatorProperties(schema, schemaUri); + resolve(JSON.stringify(schema)); + }); + }); + } + + private _resolveAggregateCollectionSchema(collectionName: string): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (_result) => { + const schema: JSONSchema = { + type: 'array', + items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) + }; + resolve(JSON.stringify(schema)); + }); + }); + } + + private getMongoDocumentType(document: any): string { + return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); + } + + private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { + if (this.getMongoDocumentType(document) === 'object') { + for (const property of Object.keys(document)) { + if (!parent && + ['_id'].indexOf(property) !== -1) { + continue; + } + this.setSchemaForDocumentProperty(parent, property, document, schema); + } + } + } + + private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { + const scopedProperty = parent ? `${parent}.${property}` : property; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const value = document[property]; + const type = this.getMongoDocumentType(value); + + const propertySchema: JSONSchema = { + type: [type, 'object'] + }; + this.setOperatorProperties(type, propertySchema); + schema.properties![scopedProperty] = propertySchema; + + if (type === 'object') { + this.setSchemaForDocument(scopedProperty, value, schema); + } + + if (type === 'array') { + for (const v of value) { + this.setSchemaForDocument(scopedProperty, v, schema); + } + } + } + + private setGlobalOperatorProperties(schema: JSONSchema): void { + schema.properties!.$text = { + type: 'object', + description: 'Performs text search', + properties: { + $search: { + type: 'string', + description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' + }, + $language: { + type: 'string', + description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' + }, + $caseSensitive: { + type: 'boolean', + description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' + }, + $diacriticSensitive: { + type: 'boolean', + description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index +Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` + } + }, + required: ['$search'] + }; + + schema.properties!.$where = { + type: 'string', + description: `Matches documents that satisfy a JavaScript expression. +Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` + }; + schema.properties!.$comment = { + type: 'string', + description: 'Adds a comment to a query predicate' + }; + } + + private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { + schema.properties!.$or = { + type: 'array', + description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', + items: { + $ref: schemaUri + } + }; + schema.properties!.$and = { + type: 'array', + description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', + items: { + $ref: schemaUri + } + }; + schema.properties!.$nor = { + type: 'array', + description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', + items: { + $ref: schemaUri + } + }; + } + + private setOperatorProperties(type: string, schema: JSONSchema): void { + if (!schema.properties) { + schema.properties = {}; + } + + const expressionSchema = { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: {} + }; + // Comparison operators + expressionSchema.properties.$eq = { + type: type, + description: 'Matches values that are equal to a specified value' + }; + expressionSchema.properties.$gt = { + type: type, + description: 'Matches values that are greater than a specified value' + }; + expressionSchema.properties.$gte = { + type: type, + description: 'Matches values that are greater than or equal to a specified value' + }; + expressionSchema.properties.$lt = { + type: type, + description: 'Matches values that are less than a specified value' + }; + expressionSchema.properties.$lte = { + type: type, + description: 'Matches values that are less than or equal to a specified value' + }; + expressionSchema.properties.$ne = { + type: type, + description: 'Matches all values that are not equal to a specified value' + }; + expressionSchema.properties.$in = { + type: 'array', + description: 'Matches any of the values specified in an array' + }; + expressionSchema.properties.$nin = { + type: 'array', + description: 'Matches none of the values specified in an array' + }; + + // Element operators + expressionSchema.properties.$exists = { + type: 'boolean', + description: 'Matches documents that have the specified field' + }; + expressionSchema.properties.$type = { + type: 'string', + description: 'Selects documents if a field is of the specified type' + }; + + // Evaluation operators + expressionSchema.properties.$mod = { + type: 'array', + description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', + maxItems: 2, + default: [2, 0] + }; + expressionSchema.properties.$regex = { + type: 'string', + description: 'Selects documents where values match a specified regular expression' + }; + + // Geospatial + const geometryPropertySchema: JSONSchema = { + type: 'object', + properties: { + type: { + type: 'string', + default: 'GeoJSON object type' + }, + coordinates: { + type: 'array' + }, + crs: { + type: 'object', + properties: { + type: { + type: 'string' + }, + properties: { + type: 'object' + } + } + } + } + }; + expressionSchema.properties.$geoWithin = { + type: 'object', + description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', + properties: { + $geometry: geometryPropertySchema, + $box: { + type: 'array' + }, + $polygon: { + type: 'array' + }, + $center: { + type: 'array' + }, + $centerSphere: { + type: 'array' + } + } + }; + expressionSchema.properties.$geoIntersects = { + type: 'object', + description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', + properties: { + $geometry: geometryPropertySchema + } + }; + expressionSchema.properties.$near = { + type: 'object', + description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: 'number' + }, + $minDistance: { + type: 'number' + } + } + }; + expressionSchema.properties.$nearSphere = { + type: 'object', + description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: 'number' + }, + $minDistance: { + type: 'number' + } + } + }; + + // Array operatos + if (type === 'array') { + expressionSchema.properties.$all = { + type: 'array', + description: 'Matches arrays that contain all elements specified in the query' + }; + expressionSchema.properties.$size = { + type: 'number', + description: 'Selects documents if the array field is a specified size' + }; + } + + // Bit operators + expressionSchema.properties.$bitsAllSet = { + type: 'array', + description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' + }; + expressionSchema.properties.$bitsAnySet = { + type: 'array', + description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' + }; + expressionSchema.properties.$bitsAllClear = { + type: 'array', + description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' + }; + expressionSchema.properties.$bitsAnyClear = { + type: 'array', + description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' + }; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + schema.properties = { ...expressionSchema.properties }; + schema.properties!.$not = { + type: 'object', + description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: { ...expressionSchema.properties } + }; + schema.properties!.$elemMatch = { + type: 'object' + }; + } + + private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { + const schemas: JSONSchema[] = []; + schemas.push({ + type: 'object', + properties: { + $collStats: { + type: 'object', + description: 'Returns statistics regarding a collection or view' + } + } + + }); + schemas.push({ + type: 'object', + properties: { + $project: { + type: 'object', + description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $match: { + type: 'object', + description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', + $ref: querySchemaUri + } + } + }); + schemas.push({ + type: 'object', + properties: { + $redact: { + type: 'object', + description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $limit: { + type: 'object', + description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $skip: { + type: 'object', + description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $unwind: { + type: 'object', + description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $group: { + type: 'object', + description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', + properties: { + _id: { + type: ['string', 'object'] + } + }, + additionalProperties: { + type: 'object' + } + } + } + }); + schemas.push({ + type: 'object', + properties: { + $sample: { + type: 'object', + description: 'Randomly selects the specified number of documents from its input' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $sort: { + type: 'object', + description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $geoNear: { + type: 'object', + description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $lookup: { + type: 'object', + description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $out: { + type: 'object', + description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $indexStats: { + type: 'object', + description: 'Returns statistics regarding the use of each index for the collection' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $facet: { + type: 'object', + description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $bucket: { + type: 'object', + description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $bucketAuto: { + type: 'object', + description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $sortByCount: { + type: 'object', + description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $addFields: { + type: 'object', + description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $replaceRoot: { + type: 'object', + description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $count: { + type: 'object', + description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $graphLookup: { + type: 'object', + description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' + } + } + }); + return { + type: 'object', + oneOf: schemas + }; + } + + private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { + if (result.length === batchSize) { + callback(result); + return; + } + + void cursor.hasNext().then(hasNext => { + if (!hasNext) { + callback(result); + return; + } + + void cursor.next().then(doc => { + result.push(doc); + this.readNext(result, cursor, batchSize, callback); + }); + }); + } + } diff --git a/Source/mongo/setConnectedNode.ts b/Source/mongo/setConnectedNode.ts index bcb8e95e1..f5680d09d 100644 --- a/Source/mongo/setConnectedNode.ts +++ b/Source/mongo/setConnectedNode.ts @@ -6,10 +6,8 @@ import { ext } from "../extensionVariables"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -export function setConnectedNode( - node: MongoDatabaseTreeItem | undefined -): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); +export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { + ext.connectedMongoDB = node; + const dbName = node && node.label; + ext.mongoCodeLensProvider.setConnectedDatabase(dbName); } diff --git a/Source/mongo/tree/IMongoTreeRoot.ts b/Source/mongo/tree/IMongoTreeRoot.ts index 262e03876..d9b68980d 100644 --- a/Source/mongo/tree/IMongoTreeRoot.ts +++ b/Source/mongo/tree/IMongoTreeRoot.ts @@ -1,8 +1,9 @@ + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ export interface IMongoTreeRoot { - isEmulator: boolean | undefined; + isEmulator: boolean | undefined; } diff --git a/Source/mongo/tree/MongoAccountTreeItem.ts b/Source/mongo/tree/MongoAccountTreeItem.ts index 2f4621afb..baa870c23 100644 --- a/Source/mongo/tree/MongoAccountTreeItem.ts +++ b/Source/mongo/tree/MongoAccountTreeItem.ts @@ -3,191 +3,138 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { - appendExtensionUserAgent, - AzExtParentTreeItem, - AzExtTreeItem, - ICreateChildImplContext, - parseError, -} from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import * as vscode from "vscode"; -import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { getThemeAgnosticIconPath, Links, testDb } from "../../constants"; -import { nonNullProp } from "../../utils/nonNull"; -import { connectToMongoClient } from "../connectToMongoClient"; -import { getDatabaseNameFromConnectionString } from "../mongoConnectionStrings"; -import { IMongoTreeRoot } from "./IMongoTreeRoot"; -import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; -import { MongoDatabaseTreeItem } from "./MongoDatabaseTreeItem"; -import { MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; +import { MongoClient } from 'mongodb'; +import * as vscode from 'vscode'; +import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; +import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; +import { nonNullProp } from '../../utils/nonNull'; +import { connectToMongoClient } from '../connectToMongoClient'; +import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; +import { IMongoTreeRoot } from './IMongoTreeRoot'; +import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; +import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; +import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor( - parent: AzExtParentTreeItem, - id: string, - label: string, - connectionString: string, - isEmulator: boolean | undefined, - readonly databaseAccount?: DatabaseAccountGetResults - ) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): - | string - | vscode.Uri - | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath("CosmosDBAccount.svg"); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error("Missing connection string"); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient( - this.connectionString, - this.databaseAccount - ? nonNullProp(this.databaseAccount, "name") - : appendExtensionUserAgent() - ); - - const databaseInConnectionString = - getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { - // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [ - { - name: databaseInConnectionString, - empty: false, - }, - ]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient - .db(testDb) - .admin() - .listDatabases(); - databases = result.databases; - } - return databases - .filter( - (database: IDatabaseInfo) => - !( - database.name && - database.name.toLowerCase() === "admin" && - database.empty - ) - ) // Filter out the 'admin' database if it's empty - .map( - (database) => - new MongoDatabaseTreeItem( - this, - nonNullProp(database, "name"), - this.connectionString - ) - ); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: "createMongoDatabase", - validateInput: validateDatabaseName, - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem( - this, - databaseName, - this.connectionString - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl( - context: IDeleteWizardContext - ): Promise { - await deleteCosmosDBAccount(context, this); - } + public static contextValue: string = "cosmosDBMongoServer"; + public readonly contextValue: string = MongoAccountTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly label: string; + public readonly connectionString: string; + + private _root: IMongoTreeRoot; + + constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { + super(parent); + this.id = id; + this.label = label; + this.connectionString = connectionString; + this._root = { isEmulator }; + this.valuesToMask.push(connectionString); + } + + // overrides ISubscriptionContext with an object that also has Mongo info + public get root(): IMongoTreeRoot { + return this._root; + } + + public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath('CosmosDBAccount.svg'); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + let mongoClient: MongoClient | undefined; + try { + let databases: IDatabaseInfo[]; + + if (!this.connectionString) { + throw new Error('Missing connection string'); + } + + // Azure MongoDB accounts need to have the name passed in for private endpoints + mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); + + const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); + if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format + // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) + databases = [{ + name: databaseInConnectionString, + empty: false + }]; + } else { + // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); + databases = result.databases; + } + return databases + .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty + .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); + } catch (error) { + const message = parseError(error).message; + if (this._root.isEmulator && message.includes("ECONNREFUSED")) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; + } + throw error; + } + finally { + if (mongoClient) { + void mongoClient.close(); + } + } + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: 'createMongoDatabase', + validateInput: validateDatabaseName + }); + context.showCreatingTreeItem(databaseName); + + return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case MongoDatabaseTreeItem.contextValue: + case MongoCollectionTreeItem.contextValue: + case MongoDocumentTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { + await deleteCosmosDBAccount(context, this); + } } -export function validateDatabaseName( - database: string -): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return 'Database name cannot contain these characters - `/\\. "$#?=`'; - } - return undefined; +export function validateDatabaseName(database: string): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions + // "#?" are restricted characters for CosmosDB - MongoDB accounts + const min = 1; + const max = 63; + if (!database || database.length < min || database.length > max) { + return `Database name must be between ${min} and ${max} characters.`; + } + if (/[/\\. "$#?=]/.test(database)) { + return "Database name cannot contain these characters - `/\\. \"$#?=`"; + } + return undefined; } export interface IDatabaseInfo { - name?: string; - empty?: boolean; + name?: string; + empty?: boolean; } diff --git a/Source/mongo/tree/MongoCollectionTreeItem.ts b/Source/mongo/tree/MongoCollectionTreeItem.ts index b4dd4f68f..eca0c8d32 100644 --- a/Source/mongo/tree/MongoCollectionTreeItem.ts +++ b/Source/mongo/tree/MongoCollectionTreeItem.ts @@ -5,473 +5,316 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { - AzExtParentTreeItem, - AzExtTreeItem, - DialogResponses, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as assert from "assert"; -import { - BulkWriteOpResultObject, - Collection, - CollectionInsertManyOptions, - Cursor, - DeleteWriteOpResultObject, - InsertOneWriteOpResult, - InsertWriteOpResult, - MongoCountPreferences, -} from "mongodb"; -import * as _ from "underscore"; -import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { nonNullValue } from "../../utils/nonNull"; -import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; -import { getBatchSizeSetting } from "../../utils/workspacUtils"; -import { MongoCommand } from "../MongoCommand"; -import { IMongoDocument, MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; +import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as assert from 'assert'; +import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; +import * as _ from 'underscore'; +import * as vscode from 'vscode'; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { nonNullValue } from '../../utils/nonNull'; +import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; +import { getBatchSizeSetting } from '../../utils/workspacUtils'; +import { MongoCommand } from '../MongoCommand'; +import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; type MongoDocument = { _id: string }; class FunctionDescriptor { - public constructor( - public mongoFunction: MongoFunction, - public text: string, - public minShellArgs: number, - public maxShellArgs: number, - public maxHandledArgs: number - ) {} + public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { + } } -export class MongoCollectionTreeItem - extends AzExtParentTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor( - parent: AzExtParentTreeItem, - collection: Collection, - findArgs?: {}[] - ) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent( - context: IActionContext, - content: string - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, "_id"), - upsert: false, - }, - }; - }); - - const result: BulkWriteOpResultObject = - await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog( - `Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)` - ); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all( - nodesToRefresh.map((n) => n.refreshChildren(context, documents)) - ); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = ( - await this.getCachedChildren(context) - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify( - children.map((c) => c.document), - null, - 2 - ); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public get filePath(): string { - return this.label + "-cosmos-collection.json"; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren( - context: IActionContext, - docs: IMongoDocument[] - ): Promise { - const documentNodes = ( - await this.getCachedChildren(context) - ); - for (const doc of docs) { - const documentNode = documentNodes.find( - (node) => node.document._id.toString() === doc._id.toString() - ); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection - .find(this._query) - .batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - "invalidMongoDocument", - (doc) => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = - await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue( - await this.collection.findOne({ _id: result.insertedId }), - "newDocument" - ); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly( - command: Partial - ): Promise< - | { deferToShell: true; result: undefined } - | { deferToShell: false; result: string } - > { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments - ? command.arguments.map(parseJSContent) - : []; - - const functions = { - drop: new FunctionDescriptor( - this.drop, - "Dropping collection", - 0, - 0, - 0 - ), - count: new FunctionDescriptor( - this.count, - "Counting documents", - 0, - 2, - 2 - ), - findOne: new FunctionDescriptor( - this.findOne, - "Finding document", - 0, - 2, - 2 - ), - insert: new FunctionDescriptor( - this.insert, - "Inserting document", - 1, - 1, - 1 - ), - insertMany: new FunctionDescriptor( - this.insertMany, - "Inserting documents", - 1, - 2, - 2 - ), - insertOne: new FunctionDescriptor( - this.insertOne, - "Inserting document", - 1, - 2, - 2 - ), - deleteMany: new FunctionDescriptor( - this.deleteMany, - "Deleting documents", - 1, - 2, - 1 - ), - deleteOne: new FunctionDescriptor( - this.deleteOne, - "Deleting document", - 1, - 2, - 1 - ), - remove: new FunctionDescriptor( - this.remove, - "Deleting document(s)", - 1, - 2, - 1 - ), - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error( - `Too few arguments passed to command ${command.name}.` - ); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error( - `Too many arguments passed to command ${command.name}` - ); - } - if (parameters.length > descriptor.maxHandledArgs) { - //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress( - descriptor.mongoFunction.apply(this, parameters), - descriptor.text - ); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteMongoCollection" }, - DialogResponses.deleteResponse - ); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number; name?: string } = e; - const NamespaceNotFoundCode = 26; - if ( - error.name === "MongoError" && - error.code === NamespaceNotFoundCode - ) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne( - query?: Object, - fieldsOption?: Object - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { - fields: fieldsOption, - }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, "\t"); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error( - "The insert command requires at least one argument" - ); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = - await this.collection.insertOne(document, { - w: options && options.writeConcern, - }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual( - documents.length, - 0, - "Array of documents cannot be empty" - ); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = - await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = - await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = - await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count( - query?: Object[], - options?: MongoCountPreferences - ): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, "\t"); - } +export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { + public static contextValue: string = "MongoCollection"; + public readonly contextValue: string = MongoCollectionTreeItem.contextValue; + public readonly childTypeLabel: string = "Document"; + public readonly collection: Collection; + public parent: AzExtParentTreeItem; + public findArgs?: {}[]; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + + private readonly _query: object | undefined; + private readonly _projection: object | undefined; + private _cursor: Cursor | undefined; + private _hasMoreChildren: boolean = true; + private _batchSize: number = getBatchSizeSetting(); + + constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { + super(parent); + this.collection = collection; + this.findArgs = findArgs; + if (findArgs && findArgs.length) { + this._query = findArgs[0]; + this._projection = findArgs.length > 1 ? findArgs[1] : undefined; + } + ext.fileSystem.fireChangedEvent(this); + } + + public async writeFileContent(context: IActionContext, content: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const documents: IMongoDocument[] = EJSON.parse(content); + const operations = documents.map((document) => { + return { + replaceOne: { + filter: { _id: document._id }, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + replacement: _.omit(document, '_id'), + upsert: false + } + }; + }); + + const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); + ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); + + // The current tree item may have been a temporary one used to execute a scrapbook command. + // We want to refresh children for this one _and_ the actual one in the tree (if it's different) + const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); + const nodesToRefresh: MongoCollectionTreeItem[] = [this]; + if (nodeInTree && this !== nodeInTree) { + nodesToRefresh.push(nodeInTree); + } + + await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); + + if (nodeInTree && this !== nodeInTree) { + // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different + ext.fileSystem.fireChangedEvent(nodeInTree); + } + } + + public async getFileContent(context: IActionContext): Promise { + const children = await this.getCachedChildren(context); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(children.map(c => c.document), null, 2); + } + + public get id(): string { + return this.collection.collectionName; + } + + public get label(): string { + return this.collection.collectionName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public get filePath(): string { + return this.label + '-cosmos-collection.json'; + } + + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + ext.fileSystem.fireChangedEvent(this); + } + + public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { + const documentNodes = await this.getCachedChildren(context); + for (const doc of docs) { + const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); + if (documentNode) { + documentNode.document = doc; + await documentNode.refresh(context); + } + } + } + + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } + + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (clearCache || this._cursor === undefined) { + this._cursor = this.collection.find(this._query).batchSize(this._batchSize); + if (this._projection) { + this._cursor = this._cursor.project(this._projection); + } + } + + const documents: IMongoDocument[] = []; + let count: number = 0; + while (count < this._batchSize) { + this._hasMoreChildren = await this._cursor.hasNext(); + if (this._hasMoreChildren) { + documents.push(await this._cursor.next()); + count += 1; + } else { + break; + } + } + this._batchSize *= 2; + + return this.createTreeItemsWithErrorHandling( + documents, + 'invalidMongoDocument', + doc => new MongoDocumentTreeItem(this, doc), + getDocumentTreeItemLabel + ); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + context.showCreatingTreeItem(""); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: InsertOneWriteOpResult = await this.collection.insertOne({}); + const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); + return new MongoDocumentTreeItem(this, newDocument); + } + + public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { + // range and text are not neccessary properties for this function so partial should suffice + const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; + + const functions = { + drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), + count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), + findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), + insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), + insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), + insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), + deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), + deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), + remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) + }; + + // eslint-disable-next-line no-prototype-builtins + if (command.name && functions.hasOwnProperty(command.name)) { + // currently no logic to handle chained commands so just defer to the shell right away + if (command.chained) { + return { deferToShell: true, result: undefined }; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const descriptor: FunctionDescriptor = functions[command.name]; + + if (parameters.length < descriptor.minShellArgs) { + throw new Error(`Too few arguments passed to command ${command.name}.`); + } + if (parameters.length > descriptor.maxShellArgs) { + throw new Error(`Too many arguments passed to command ${command.name}`); + } + if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will + return { deferToShell: true, result: undefined }; + } + const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); + return { deferToShell: false, result }; + } + return { deferToShell: true, result: undefined }; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); + await this.drop(); + } + + private async drop(): Promise { + try { + await this.collection.drop(); + return `Dropped collection '${this.collection.collectionName}'.`; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const error: { code?: number, name?: string } = e; + const NamespaceNotFoundCode = 26; + if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { + return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; + } else { + throw error; + } + } + } + + private async findOne(query?: Object, fieldsOption?: Object): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); + // findOne is the only command in this file whose output requires EJSON support. + // Hence that's the only function which uses EJSON.stringify rather than this.stringify. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(result, null, '\t'); + } + + private async insert(document: Object): Promise { + if (!document) { + throw new Error("The insert command requires at least one argument"); + } + + const insertResult = await this.collection.insert(document); + return this.stringify(insertResult); + } + + private async insertOne(document: Object, options?: any): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); + return this.stringify(insertOneResult); + } + + private async insertMany(documents: any[], options?: any): Promise { + assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); + const insertManyOptions: CollectionInsertManyOptions = {}; + if (options) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.ordered) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.ordered = options.ordered; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.writeConcern) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.w = options.writeConcern; + } + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); + return this.stringify(insertManyResult); + } + + private async remove(filter: Object): Promise { + const removeResult = await this.collection.remove(filter); + return this.stringify(removeResult); + } + + private async deleteOne(filter: Object): Promise { + const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); + return this.stringify(deleteOneResult); + } + + private async deleteMany(filter: Object): Promise { + const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); + return this.stringify(deleteOpResult); + } + + private async count(query?: Object[], options?: MongoCountPreferences): Promise { + const count = await this.collection.count(query, options); + return this.stringify(count); + } + + private stringify(result: any): string { + return JSON.stringify(result, null, '\t'); + } } function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title, - }, - (_progress) => { - return promise; - } - ); + return vscode.window.withProgress( + { + location: vscode.ProgressLocation.Window, + title: title + }, + (_progress) => { + return promise; + }); } function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.parse(content); + } catch (error) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + throw error.message; + } } diff --git a/Source/mongo/tree/MongoDatabaseTreeItem.ts b/Source/mongo/tree/MongoDatabaseTreeItem.ts index 1fed13c80..73a7c6a22 100644 --- a/Source/mongo/tree/MongoDatabaseTreeItem.ts +++ b/Source/mongo/tree/MongoDatabaseTreeItem.ts @@ -3,383 +3,256 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - appendExtensionUserAgent, - AzExtParentTreeItem, - DialogResponses, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, - UserCancelledError, -} from "@microsoft/vscode-azext-utils"; -import * as fse from "fs-extra"; -import { Collection, Db, DbCollectionOptions } from "mongodb"; -import * as path from "path"; -import * as process from "process"; -import * as vscode from "vscode"; -import { ext } from "../../extensionVariables"; -import * as cpUtils from "../../utils/cp"; -import { nonNullProp, nonNullValue } from "../../utils/nonNull"; -import { connectToMongoClient } from "../connectToMongoClient"; -import { MongoCommand } from "../MongoCommand"; -import { addDatabaseToAccountConnectionString } from "../mongoConnectionStrings"; -import { MongoShell } from "../MongoShell"; -import { IMongoTreeRoot } from "./IMongoTreeRoot"; -import { MongoAccountTreeItem } from "./MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; - -const mongoExecutableFileName = - process.platform === "win32" ? "mongo.exe" : "mongo"; +import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import { Collection, Db, DbCollectionOptions } from 'mongodb'; +import * as path from 'path'; +import * as process from 'process'; +import * as vscode from 'vscode'; +import { ext } from '../../extensionVariables'; +import * as cpUtils from '../../utils/cp'; +import { nonNullProp, nonNullValue } from '../../utils/nonNull'; +import { connectToMongoClient } from '../connectToMongoClient'; +import { MongoCommand } from '../MongoCommand'; +import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; +import { MongoShell } from '../MongoShell'; +import { IMongoTreeRoot } from './IMongoTreeRoot'; +import { MongoAccountTreeItem } from './MongoAccountTreeItem'; +import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; + +const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; const executingInShellMsg = "Executing command in Mongo shell"; export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor( - parent: MongoAccountTreeItem, - databaseName: string, - connectionString: string - ) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString( - connectionString, - this.databaseName - ); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && - ext.connectedMongoDB.fullId === this.fullId - ? "Connected" - : ""; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("database"); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map( - (collection) => new MongoCollectionTreeItem(this, collection) - ); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: "createMongoCollection", - validateInput: validateMongoCollectionName, - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteMongoDatabase" }, - DialogResponses.deleteResponse - ); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient( - this.connectionString, - appendExtensionUserAgent() - ); - return accountConnection.db(this.databaseName); - } - - public async executeCommand( - command: MongoCommand, - context: IActionContext - ): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem( - this, - collection, - command.arguments - ); - const result = - await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress( - this.executeCommandInShell(command, context), - executingInShellMsg - ); - } - - if (command.name === "createCollection") { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress( - this.createCollection( - stripQuotes(nonNullProp(command, "arguments")[0]), - nonNullProp(command, "argumentObjects")[1] - ).then(() => JSON.stringify({ Created: "Ok" })), - "Creating collection" - ); - } else { - return withProgress( - this.executeCommandInShell(command, context), - executingInShellMsg - ); - } - } - - public async createCollection( - collectionName: string, - options?: DbCollectionOptions - ): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection( - collectionName, - options - ); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell( - command: MongoCommand, - context: IActionContext - ): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get( - ext.settingsKeys.mongoShellPath - ); - const shellArgs: string[] = config.get( - ext.settingsKeys.mongoShellArgs, - [] - ); - - if ( - !shellPath || - !this._cachedShellPathOrCmd || - this._previousShellPathSetting !== shellPath - ) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = - 1000 * - nonNullValue( - config.get(ext.settingsKeys.mongoShellTimeout), - "mongoShellTimeout" - ); - return MongoShell.create( - shellPath, - shellArgs, - this.connectionString, - this.root.isEmulator, - ext.outputChannel, - timeout - ); - } - - private async _determineShellPathOrCmd( - context: IActionContext, - shellPathSetting: string | undefined - ): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds("mongo", "--version")) { - // If the user already has mongo in their system path, just use that - return "mongo"; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { - title: `Browse to ${mongoExecutableFileName}`, - }; - const browse: vscode.MessageItem = { - title: "Open installation page", - }; - const noMongoError: string = - "This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting."; - const response = await context.ui.showWarningMessage( - noMongoError, - { stepName: "promptForMongoPath" }, - browse, - openFile - ); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = - await context.ui.showOpenDialog({ - filters: { - "Executable Files": [ - process.platform === "win32" - ? "exe" - : "", - ], - }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: "openMongoExeFile", - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { - title: "Use anyway", - }; - const tryAgain: vscode.MessageItem = { - title: "Try again", - }; - const response2 = - await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: "confirmMongoExeFile" }, - useAnyway, - tryAgain - ); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace - .getConfiguration() - .update( - ext.settingsKeys.mongoShellPath, - fsPath, - vscode.ConfigurationTarget.Global - ); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand( - "vscode.open", - vscode.Uri.parse( - "https://docs.mongodb.com/manual/installation/" - ) - ); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError("createShell"); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } + public static contextValue: string = "mongoDb"; + public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; + public readonly connectionString: string; + public readonly databaseName: string; + public readonly parent: MongoAccountTreeItem; + + private _previousShellPathSetting: string | undefined; + private _cachedShellPathOrCmd: string | undefined; + + constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { + super(parent); + this.databaseName = databaseName; + this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); + } + + public get root(): IMongoTreeRoot { + return this.parent.root; + } + + public get label(): string { + return this.databaseName; + } + + public get description(): string { + return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; + } + + public get id(): string { + return this.databaseName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('database'); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + const db: Db = await this.connectToDb(); + const collections: Collection[] = await db.collections(); + return collections.map(collection => new MongoCollectionTreeItem(this, collection)); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + const collectionName = await context.ui.showInputBox({ + placeHolder: "Collection Name", + prompt: "Enter the name of the collection", + stepName: 'createMongoCollection', + validateInput: validateMongoCollectionName + }); + + context.showCreatingTreeItem(collectionName); + return await this.createCollection(collectionName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); + const db = await this.connectToDb(); + await db.dropDatabase(); + } + + public async connectToDb(): Promise { + const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); + return accountConnection.db(this.databaseName); + } + + public async executeCommand(command: MongoCommand, context: IActionContext): Promise { + if (command.collection) { + const db = await this.connectToDb(); + const collection = db.collection(command.collection); + if (collection) { + const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); + const result = await collectionTreeItem.tryExecuteCommandDirectly(command); + if (!result.deferToShell) { + return result.result; + } + } + return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); + + } + + if (command.name === 'createCollection') { + // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead + return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); + } else { + return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); + } + } + + public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { + const db: Db = await this.connectToDb(); + const newCollection: Collection = await db.createCollection(collectionName, options); + // db.createCollection() doesn't create empty collections for some reason + // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection + const result = await newCollection.insertOne({}); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + await newCollection.deleteOne({ _id: result.insertedId }); + return new MongoCollectionTreeItem(this, newCollection); + } + + private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { + context.telemetry.properties.executeInShell = "true"; + + if (this.root.isEmulator) { + // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info + await this.connectToDb(); + } + + // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state + // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out + // requests. + const shell = await this.createShell(context); + try { + await shell.useDatabase(this.databaseName); + return await shell.executeScript(command.text); + } finally { + shell.dispose(); + } + } + + private async createShell(context: IActionContext): Promise { + const config = vscode.workspace.getConfiguration(); + let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); + const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); + + if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { + // Only do this if setting changed since last time + shellPath = await this._determineShellPathOrCmd(context, shellPath); + this._previousShellPathSetting = shellPath; + } + this._cachedShellPathOrCmd = shellPath; + + const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); + return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); + } + + private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { + if (!shellPathSetting) { + // User hasn't specified the path + if (await cpUtils.commandSucceeds('mongo', '--version')) { + // If the user already has mongo in their system path, just use that + return 'mongo'; + } else { + // If all else fails, prompt the user for the mongo path + const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; + const browse: vscode.MessageItem = { title: 'Open installation page' }; + const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; + const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); + if (response === openFile) { + // eslint-disable-next-line no-constant-condition + while (true) { + const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ + filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, + openLabel: `Select ${mongoExecutableFileName}`, + stepName: 'openMongoExeFile', + }); + const fsPath = newPath[0].fsPath; + const baseName = path.basename(fsPath); + if (baseName !== mongoExecutableFileName) { + const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; + const tryAgain: vscode.MessageItem = { title: 'Try again' }; + const response2 = await context.ui.showWarningMessage( + `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, + { stepName: 'confirmMongoExeFile' }, + useAnyway, + tryAgain); + if (response2 === tryAgain) { + continue; + } + } + + await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); + return fsPath; + } + } else if (response === browse) { + void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); + // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath + } + + throw new UserCancelledError('createShell'); + } + } else { + // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix + if (await fse.pathExists(shellPathSetting)) { + const stat = await fse.stat(shellPathSetting); + if (stat.isDirectory()) { + return path.join(shellPathSetting, mongoExecutableFileName); + } + } + + return shellPathSetting; + } + } } -export function validateMongoCollectionName( - collectionName: string -): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; +export function validateMongoCollectionName(collectionName: string): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names + if (!collectionName) { + return "Collection name cannot be empty"; + } + const systemPrefix = "system."; + if (collectionName.startsWith(systemPrefix)) { + return `"${systemPrefix}" prefix is reserved for internal use`; + } + if (/[$]/.test(collectionName)) { + return "Collection name cannot contain $"; + } + return undefined; } -function withProgress( - promise: Thenable, - title: string, - location: vscode.ProgressLocation = vscode.ProgressLocation.Window -): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title, - }, - (_progress) => { - return promise; - } - ); +function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { + return vscode.window.withProgress( + { + location: location, + title: title + }, + (_progress) => { + return promise; + }); } export function stripQuotes(term: string): string { - if ( - (term.startsWith("'") && term.endsWith("'")) || - (term.startsWith('"') && term.endsWith('"')) - ) { - return term.substring(1, term.length - 1); - } - return term; + if ((term.startsWith('\'') && term.endsWith('\'')) + || (term.startsWith('"') && term.endsWith('"'))) { + return term.substring(1, term.length - 1); + } + return term; } diff --git a/Source/mongo/tree/MongoDocumentTreeItem.ts b/Source/mongo/tree/MongoDocumentTreeItem.ts index dae87ed84..ad44e43c3 100644 --- a/Source/mongo/tree/MongoDocumentTreeItem.ts +++ b/Source/mongo/tree/MongoDocumentTreeItem.ts @@ -3,131 +3,95 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { - Collection, - DeleteWriteOpResultObject, - ObjectID, - UpdateWriteOpResult, -} from "mongodb"; -import * as _ from "underscore"; -import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; -import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; +import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; +import * as _ from 'underscore'; +import * as vscode from 'vscode'; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; +import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); export interface IMongoDocument { - _id: string | ObjectID; + _id: string | ObjectID; - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + // custom properties + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [key: string]: any; } -export class MongoDocumentTreeItem - extends AzExtTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); +export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { + public static contextValue: string = "MongoDocument"; + public readonly contextValue: string = MongoDocumentTreeItem.contextValue; + public document: IMongoDocument; + public readonly parent: MongoCollectionTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); - private _label: string; + private _label: string; - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = "cosmosDB.openDocument"; - ext.fileSystem.fireChangedEvent(this); - } + constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { + super(parent); + this.document = document; + this._label = getDocumentTreeItemLabel(this.document); + this.commandId = 'cosmosDB.openDocument'; + ext.fileSystem.fireChangedEvent(this); + } - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } + public get id(): string { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return String(this.document!._id); + } - public get label(): string { - return this._label; - } + public get label(): string { + return this._label; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("file"); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('file'); + } - public get filePath(): string { - return this.label + "-cosmos-document.json"; - } + public get filePath(): string { + return this.label + '-cosmos-document.json'; + } - public static async update( - collection: Collection, - newDocument: IMongoDocument - ): Promise { - if (!newDocument._id) { - throw new Error( - `The "_id" field is required to update a document.` - ); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne( - filter, - _.omit(newDocument, "_id") - ); - if (result.modifiedCount !== 1) { - throw new Error( - `Failed to update document with _id '${newDocument._id}'.` - ); - } - return newDocument; - } + public static async update(collection: Collection, newDocument: IMongoDocument): Promise { + if (!newDocument._id) { + throw new Error(`The "_id" field is required to update a document.`); + } + const filter: object = { _id: newDocument._id }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); + if (result.modifiedCount !== 1) { + throw new Error(`Failed to update document with _id '${newDocument._id}'.`); + } + return newDocument; + } - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } + public async getFileContent(): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(this.document, null, 2); + } - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this.document); + ext.fileSystem.fireChangedEvent(this); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteMongoDocument" }, - DialogResponses.deleteResponse - ); - const deleteResult: DeleteWriteOpResultObject = - await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error( - `Failed to delete document with _id '${this.document._id}'.` - ); - } - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this._label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); + const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); + if (deleteResult.deletedCount !== 1) { + throw new Error(`Failed to delete document with _id '${this.document._id}'.`); + } + } - public async writeFileContent( - _context: IActionContext, - content: string - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update( - this.parent.collection, - newDocument - ); - } + public async writeFileContent(_context: IActionContext, content: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const newDocument: IMongoDocument = EJSON.parse(content); + this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); + } } diff --git a/Source/postgres/abstract/AbstractPostgresClient.ts b/Source/postgres/abstract/AbstractPostgresClient.ts index ca6bd3d9a..c1fa29c4f 100644 --- a/Source/postgres/abstract/AbstractPostgresClient.ts +++ b/Source/postgres/abstract/AbstractPostgresClient.ts @@ -6,26 +6,18 @@ import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../../utils/azureClients"; +import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; import { PostgresServerType } from "./models"; -export type AbstractPostgresClient = - | PostgreSQLFlexibleManagementClient - | PostgreSQLSingleManagementClient; +export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; -export async function createAbstractPostgresClient( - serverType: PostgresServerType, - context: AzExtClientContext -): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context); - case PostgresServerType.Single: - return await createPostgreSQLClient(context); - default: - throw new Error("Service not implemented."); - } +export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { + switch (serverType) { + case PostgresServerType.Flexible: + return await createPostgreSQLFlexibleClient(context) + case PostgresServerType.Single: + return await createPostgreSQLClient(context) + default: + throw new Error("Service not implemented."); + } } diff --git a/Source/postgres/abstract/models.ts b/Source/postgres/abstract/models.ts index 046185de1..6bdadf16a 100644 --- a/Source/postgres/abstract/models.ts +++ b/Source/postgres/abstract/models.ts @@ -7,58 +7,49 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; export enum PostgresServerType { - Flexible = "Flexible", - Single = "Single", + Flexible = 'Flexible', + Single = 'Single' } -export type PostgresAbstractServer = ( - | SingleModels.Server - | FlexibleModels.Server -) & { serverType?: PostgresServerType }; +export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } -export type PostgresAbstractDatabase = - | SingleModels.Database - | FlexibleModels.Database; +export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; /** * Billing information related properties of a server. */ export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; + /** + * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + */ + name: string; + /** + * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', + * 'GeneralPurpose', 'MemoryOptimized' + */ + tier: SingleModels.SkuTier | FlexibleModels.SkuTier; + /** + * The scale up/out capacity, representing server's compute units. + */ + capacity?: number; + /** + * The size code, to be interpreted by resource as appropriate. + */ + size?: string; + /** + * The family of hardware. + */ + family?: string; } export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; + location: string; + sku: AbstractSku; + administratorLogin: string; + administratorLoginPassword: string; + size: number; } -export type AbstractNameAvailability = - | SingleModels.NameAvailability - | FlexibleModels.NameAvailability; +export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; -export type AbstractFirewallRule = - | SingleModels.FirewallRule - | FlexibleModels.FirewallRule; +export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; diff --git a/Source/postgres/commands/checkAuthentication.ts b/Source/postgres/commands/checkAuthentication.ts index c26bc25be..6799d060c 100644 --- a/Source/postgres/commands/checkAuthentication.ts +++ b/Source/postgres/commands/checkAuthentication.ts @@ -3,11 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - IActionContext, - IParsedError, - parseError, -} from "@microsoft/vscode-azext-utils"; +import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; import { invalidCredentialsErrorType } from "../postgresConstants"; import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; @@ -15,34 +11,26 @@ import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; import { configurePostgresFirewall } from "./configurePostgresFirewall"; import { enterPostgresCredentials } from "./enterPostgresCredentials"; -export async function checkAuthentication( - context: IActionContext, - treeItem: PostgresDatabaseTreeItem -): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = - await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = - await PostgresClientConfigFactory.getClientConfigFromNode( - treeItem.parent, - treeItem.databaseName - ); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); +export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { + let clientConfig: ClientConfig | undefined; + while (!clientConfig) { + const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + await configurePostgresFirewall(context, treeItem.parent); + continue; + } + try { + const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); + clientConfig = getClientConfigResult.clientConfig; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; + if (parsedError.errorType === invalidCredentialsErrorType) { + await enterPostgresCredentials(context, treeItem.parent); + } else { + throw error; + } + } + } + return clientConfig; } diff --git a/Source/postgres/commands/configurePostgresFirewall.ts b/Source/postgres/commands/configurePostgresFirewall.ts index 86779ff9b..52a378fca 100644 --- a/Source/postgres/commands/configurePostgresFirewall.ts +++ b/Source/postgres/commands/configurePostgresFirewall.ts @@ -4,102 +4,66 @@ *--------------------------------------------------------------------------------------------*/ import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; +import * as vscode from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { getPublicIpv4 } from "../../utils/getIp"; import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { randomUtils } from "../../utils/randomUtils"; -import { - AbstractPostgresClient, - createAbstractPostgresClient, -} from "../abstract/AbstractPostgresClient"; -import { AbstractFirewallRule, PostgresServerType } from "../abstract/models"; +import { nonNullProp } from '../../utils/nonNull'; +import { randomUtils } from '../../utils/randomUtils'; +import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; +import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function configurePostgresFirewall( - context: IActionContext, - treeItem?: PostgresServerTreeItem -): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } +export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize( - "firewallRuleWillBeAdded", - 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', - ip, - treeItem.label - ), - { - modal: true, - stepName: "postgresAddFirewallRule", - }, - { title: DialogResponses.yes.title } - ); + const ip: string = await getPublicIp(context); + await context.ui.showWarningMessage( + localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), + { + modal: true, + stepName: 'postgresAddFirewallRule' + }, + { title: DialogResponses.yes.title } + ); - await setFirewallRule(context, treeItem, ip); + await setFirewallRule(context, treeItem, ip); } -export async function setFirewallRule( - context: IActionContext, - treeItem: PostgresServerTreeItem, - ip: string -): Promise { - const serverType: PostgresServerType = nonNullProp(treeItem, "serverType"); - const client: AbstractPostgresClient = await createAbstractPostgresClient( - serverType, - [context, treeItem.subscription] - ); - const resourceGroup: string = nonNullProp(treeItem, "resourceGroup"); - const serverName: string = nonNullProp(treeItem, "azureName"); +export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { - const firewallRuleName: string = - "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; + const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); + const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); + const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); + const serverName: string = nonNullProp(treeItem, 'azureName'); - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip, - }; + const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - const progressMessage: string = localize( - "configuringFirewallRule", - 'Adding firewall rule for IP "{0}" to server "{1}"...', - ip, - serverName - ); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage, - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait( - resourceGroup, - serverName, - firewallRuleName, - newFirewallRule - ); - }); - const completedMessage: string = localize( - "addedFirewallRule", - 'Successfully added firewall rule for IP "{0}" to server "{1}".', - ip, - serverName - ); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); + const newFirewallRule: AbstractFirewallRule = { + startIpAddress: ip, + endIpAddress: ip + }; + + const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage + }; + ext.outputChannel.appendLog(progressMessage); + await vscode.window.withProgress(options, async () => { + await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); + }); + const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + await treeItem.refresh(context); } export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); + return await getPublicIpv4(context); } diff --git a/Source/postgres/commands/connectPostgresDatabase.ts b/Source/postgres/commands/connectPostgresDatabase.ts index 9437c8c70..6996f7d03 100644 --- a/Source/postgres/commands/connectPostgresDatabase.ts +++ b/Source/postgres/commands/connectPostgresDatabase.ts @@ -4,52 +4,36 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from "vscode"; -import { - connectedPostgresKey, - postgresFlexibleFilter, - postgresSingleFilter, -} from "../../constants"; +import { Uri, window } from 'vscode'; +import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; import { ext } from "../../extensionVariables"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function connectPostgresDatabase( - context: IActionContext, - treeItem?: Uri | PostgresDatabaseTreeItem -): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } +export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { + if (!treeItem || treeItem instanceof Uri) { + if (treeItem) { + void window.showTextDocument(treeItem); + } + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } - const oldTreeItemId: string | undefined = - ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); + const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; + void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); + ext.connectedPostgresDB = treeItem; + const database = treeItem && treeItem.label; + if (ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(database); + } + await treeItem.refresh(context); - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - oldTreeItemId, - context - ); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } + if (oldTreeItemId) { + // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); + if (oldTreeItem) { + await oldTreeItem.refresh(context); + } + } } diff --git a/Source/postgres/commands/copyConnectionString.ts b/Source/postgres/commands/copyConnectionString.ts index 6d9bcbcf2..716bbd5b6 100644 --- a/Source/postgres/commands/copyConnectionString.ts +++ b/Source/postgres/commands/copyConnectionString.ts @@ -3,56 +3,34 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { - addDatabaseToConnectionString, - copyPostgresConnectionString, -} from "../postgresConnectionStrings"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { checkAuthentication } from "./checkAuthentication"; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; +import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; +import { checkAuthentication } from './checkAuthentication'; -export async function copyConnectionString( - context: IActionContext, - node: PostgresDatabaseTreeItem -): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } +export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString( - parsedCS.hostName, - parsedCS.port, - parsedCS.username, - parsedCS.password, - node.databaseName - ); - } else { - connectionString = addDatabaseToConnectionString( - parsedConnectionString.connectionString, - node.databaseName - ); - } + await checkAuthentication(context, node); + const parsedConnectionString = await node.parent.getFullConnectionString(); + let connectionString: string; + if (node.parent.azureName) { + const parsedCS = await node.parent.getFullConnectionString(); + connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); + } else { + connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); + } - await vscode.env.clipboard.writeText(connectionString); - const message = localize( - "copiedPostgresConnectStringMsg", - "The connection string has been copied to the clipboard" - ); - void vscode.window.showInformationMessage(message); + await vscode.env.clipboard.writeText(connectionString); + const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); + void vscode.window.showInformationMessage(message); } diff --git a/Source/postgres/commands/createPostgresDatabase.ts b/Source/postgres/commands/createPostgresDatabase.ts index c86e5ac45..6c096a52b 100644 --- a/Source/postgres/commands/createPostgresDatabase.ts +++ b/Source/postgres/commands/createPostgresDatabase.ts @@ -3,35 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -import { connectPostgresDatabase } from "./connectPostgresDatabase"; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; +import { connectPostgresDatabase } from './connectPostgresDatabase'; -export async function createPostgresDatabase( - context: IActionContext, - node?: PostgresServerTreeItem -): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } - const newDatabase: PostgresDatabaseTreeItem = - await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize( - "createPostgresDatabaseMsg", - 'Successfully created database "{0}".', - newDatabase.databaseName - ); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); +export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } + const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); + await connectPostgresDatabase(context, newDatabase); + const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); } diff --git a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts index 64a4fe0b5..81d54b9af 100644 --- a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts @@ -1,3 +1,4 @@ + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -6,6 +7,6 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; + name?: string; + query?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts index 8b4dd5f93..27b32993c 100644 --- a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts @@ -5,7 +5,6 @@ import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; -export interface IPostgresFunctionQueryWizardContext - extends IPostgresQueryWizardContext { - returnType?: string; +export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { + returnType?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts index ca281d4d4..8c4df098b 100644 --- a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts @@ -11,19 +11,13 @@ import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; -export async function createPostgresFunctionQuery( - context: IActionContext, - treeItem?: PostgresFunctionsTreeItem -): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [ - new FunctionQueryNameStep(), - new FunctionQueryReturnTypeStep(), - ], - executeSteps: [new FunctionQueryCreateStep()], - title: "Create PostgreSQL Function Query", - }); +export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { + const wizardContext: IPostgresFunctionQueryWizardContext = context; + const wizard = new AzureWizard(wizardContext, { + promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], + executeSteps: [new FunctionQueryCreateStep()], + title: 'Create PostgreSQL Function Query' + }); - await runPostgresQueryWizard(wizard, wizardContext, treeItem); + await runPostgresQueryWizard(wizard, wizardContext, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts index 9c0bd1e34..9356882d9 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts @@ -9,26 +9,18 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute( - context: IPostgresFunctionQueryWizardContext - ): Promise { - context.query = defaultFunctionQuery( - nonNullProp(context, "name"), - nonNullProp(context, "returnType") - ); - } + public async execute(context: IPostgresFunctionQueryWizardContext): Promise { + context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultFunctionQuery = ( - name: string, - returnType: string -) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) +const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) RETURNS ${returnType} LANGUAGE plpgsql AS $function$ diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts index a37c18995..cfacc0f64 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts @@ -8,18 +8,11 @@ import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresFunctionQueryWizardContext - ): Promise { - context.returnType = await context.ui.showInputBox({ - prompt: localize( - "provideCustomReturnType", - "Provide custom return type" - ), - }); - } + public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { + context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts index 78459f842..36d798074 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts @@ -9,21 +9,14 @@ import { validateIdentifier } from "../../validateIdentifier"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresFunctionQueryWizardContext - ): Promise { - context.name = ( - await context.ui.showInputBox({ - prompt: localize( - "provideFunctionName", - "Provide function name" - ), - validateInput: validateIdentifier, - }) - ).trim(); - } + public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { + context.name = (await context.ui.showInputBox({ + prompt: localize('provideFunctionName', 'Provide function name'), + validateInput: validateIdentifier + })).trim(); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts index b69c94a2c..63f703793 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts @@ -3,71 +3,48 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzureWizardPromptStep, - IAzureQuickPickItem, - IWizardOptions, -} from "@microsoft/vscode-azext-utils"; +import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresFunctionQueryWizardContext - ): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = - returnTypes.map((r) => { - return { label: r, data: r }; - }); - returnTypeQuickPicks.push({ - label: localize( - "enterCustomReturnType", - "$(pencil) Enter custom return type..." - ), - data: undefined, - }); + public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { + const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); + returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); - context.returnType = ( - await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize("selectReturnType", "Select return type"), - }) - ).data; - } + context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { + placeHolder: localize('selectReturnType', 'Select return type') + })).data; + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } - public async getSubWizard( - context: IPostgresFunctionQueryWizardContext - ): Promise< - IWizardOptions | undefined - > { - return context.returnType - ? undefined - : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } + public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { + return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; + } } // A subset of return types available on pgAdmin const returnTypes: string[] = [ - "bigint", - "bigint[]", - "boolean", - "boolean[]", - "character", - "character[]", - "date", - "date[]", - "integer", - "integer[]", - "json", - "json[]", - "oid", - "oid[]", - "smallint", - "smallint[]", - "text", - "void", + 'bigint', + 'bigint[]', + 'boolean', + 'boolean[]', + 'character', + 'character[]', + 'date', + 'date[]', + 'integer', + 'integer[]', + 'json', + 'json[]', + 'oid', + 'oid[]', + 'smallint', + 'smallint[]', + 'text', + 'void' ]; diff --git a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts index 65288da3d..925695e56 100644 --- a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts @@ -4,31 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { - postgresBaseFileName, - postgresFileExtension, -} from "../../../constants"; +import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from "../../../utils/vscodeUtils"; +import * as vscodeUtil from '../../../utils/vscodeUtils'; import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; import { connectPostgresDatabase } from "../connectPostgresDatabase"; import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; -export async function runPostgresQueryWizard( - wizard: AzureWizard, - context: IPostgresQueryWizardContext, - treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem -): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile( - nonNullProp(context, "query"), - postgresBaseFileName, - postgresFileExtension - ); +export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { + await wizard.prompt(); + await wizard.execute(); + await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } + if (treeItem) { + await connectPostgresDatabase(context, treeItem.parent); + } } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts index b63bf39ae..f1ddbe51b 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts @@ -9,15 +9,12 @@ import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; -export async function createPostgresStoredProcedureQuery( - context: IActionContext, - treeItem?: PostgresStoredProceduresTreeItem -): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: "Create PostgreSQL Stored Procedure Query", - }); +export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { + const wizard = new AzureWizard(context, { + promptSteps: [new StoredProcedureQueryNameStep()], + executeSteps: [new StoredProcedureQueryCreateStep()], + title: 'Create PostgreSQL Stored Procedure Query' + }); - await runPostgresQueryWizard(wizard, context, treeItem); + await runPostgresQueryWizard(wizard, context, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts index 67bbbbf0c..2cf3ef916 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts @@ -9,22 +9,18 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery( - nonNullProp(context, "name") - ); - } + public async execute(context: IPostgresQueryWizardContext): Promise { + context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultStoredProcedureQuery = ( - name: string -) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) +const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) LANGUAGE plpgsql AS $$ BEGIN diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts index 5b694f378..bf9a00392 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts @@ -9,19 +9,14 @@ import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; import { validateIdentifier } from "../../validateIdentifier"; export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = ( - await context.ui.showInputBox({ - prompt: localize( - "provideStoredProcedureName", - "Provide stored procedure name" - ), - validateInput: validateIdentifier, - }) - ).trim(); - } + public async prompt(context: IPostgresQueryWizardContext): Promise { + context.name = (await context.ui.showInputBox({ + prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), + validateInput: validateIdentifier + })).trim(); + } - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts index 94bb16657..9339f6796 100644 --- a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts @@ -6,123 +6,108 @@ import { localize } from "../../../utils/localize"; export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); + // Identifier naming rules: https://aka.ms/AA8618j + identifier = identifier.trim(); - const min = 1; - const max = 63; + const min = 1; + const max = 63; - if (identifier.length < min || identifier.length > max) { - return localize( - "postgresResourcesNameLengthCheck", - "The name must be between {0} and {1} characters.", - min, - max - ); - } + if (identifier.length < min || identifier.length > max) { + return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); + } - if (!identifier[0].match(/[a-z_]/i)) { - return localize( - "mustStartWithLetterOrUnderscore", - "Name must start with a letter or underscore." - ); - } + if (!identifier[0].match(/[a-z_]/i)) { + return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); + } - if (identifier.match(/[^a-z_\d$]/i)) { - return localize( - "canOnlyContainCertainCharacters", - "Name can only contain letters, underscores, digits (0-9), and dollar signs ($)." - ); - } + if (identifier.match(/[^a-z_\d$]/i)) { + return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); + } - if (reservedWords.has(identifier.toLowerCase())) { - return localize( - "cantBeReservedWord", - 'Name cannot be reserved word "{0}".', - identifier - ); - } + if (reservedWords.has(identifier.toLowerCase())) { + return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); + } - return undefined; + return undefined; } // Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html const reservedWords: Set = new Set([ - "all", - "analyse", - "analyze", - "and", - "any", - "array", - "as", - "asc", - "asymmetric", - "both", - "case", - "cast", - "check", - "collate", - "column", - "constraint", - "create", - "current_catalog", - "current_date", - "current_role", - "current_time", - "current_timestamp", - "current_user", - "default", - "deferrable", - "desc", - "distinct", - "do", - "else", - "end", - "except", - "false", - "fetch", - "for", - "foreign", - "from", - "grant", - "group", - "having", - "in", - "initially", - "intersect", - "into", - "lateral", - "leading", - "limit", - "localtime", - "localtimestamp", - "not", - "null", - "offset", - "on", - "only", - "or", - "order", - "placing", - "primary", - "references", - "returning", - "select", - "session_user", - "some", - "symmetric", - "table", - "then", - "to", - "trailing", - "true", - "union", - "unique", - "user", - "using", - "variadic", - "when", - "where", - "window", - "with", + 'all', + 'analyse', + 'analyze', + 'and', + 'any', + 'array', + 'as', + 'asc', + 'asymmetric', + 'both', + 'case', + 'cast', + 'check', + 'collate', + 'column', + 'constraint', + 'create', + 'current_catalog', + 'current_date', + 'current_role', + 'current_time', + 'current_timestamp', + 'current_user', + 'default', + 'deferrable', + 'desc', + 'distinct', + 'do', + 'else', + 'end', + 'except', + 'false', + 'fetch', + 'for', + 'foreign', + 'from', + 'grant', + 'group', + 'having', + 'in', + 'initially', + 'intersect', + 'into', + 'lateral', + 'leading', + 'limit', + 'localtime', + 'localtimestamp', + 'not', + 'null', + 'offset', + 'on', + 'only', + 'or', + 'order', + 'placing', + 'primary', + 'references', + 'returning', + 'select', + 'session_user', + 'some', + 'symmetric', + 'table', + 'then', + 'to', + 'trailing', + 'true', + 'union', + 'unique', + 'user', + 'using', + 'variadic', + 'when', + 'where', + 'window', + 'with' ]); diff --git a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts index cc28cd581..390c1cf42 100644 --- a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts @@ -5,26 +5,20 @@ import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { - AbstractSku, - PostgresAbstractServer, - PostgresServerType, -} from "../../abstract/models"; +import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; -export interface IPostgresServerWizardContext - extends IAzureDBWizardContext, - ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; +export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { + /** + * Username without server, i.e. "user1" + */ + shortUserName?: string; + /** + * Username with server, i.e. "user1@server1" + */ + longUserName?: string; + adminPassword?: string; - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; + server?: PostgresAbstractServer; + sku?: AbstractSku; + serverType?: PostgresServerType; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts index 20d13ffbf..2f07d8203 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts @@ -8,30 +8,24 @@ import { localize } from "../../../../utils/localize"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize("confirmPW", "Confirm your password"); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async ( - value: string | undefined - ): Promise => - await this.validatePassword(context, value), - }); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const prompt: string = localize('confirmPW', 'Confirm your password'); + await context.ui.showInputBox({ + prompt, + password: true, + validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) + }); + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !!context.adminPassword; + } - private async validatePassword( - context: IPostgresServerWizardContext, - passphrase: string | undefined - ): Promise { - if (passphrase !== context.adminPassword) { - return localize("pwMatch", "The passwords must match."); - } + private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { + if (passphrase !== context.adminPassword) { + return localize('pwMatch', 'The passwords must match.'); + } - return undefined; - } + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts index 549f1e67f..f73ce810d 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts @@ -5,133 +5,100 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { - AzureWizardExecuteStep, - callWithMaskHandling, -} from "@microsoft/vscode-azext-utils"; +import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from "vscode"; -import { ext } from "../../../../extensionVariables"; -import { - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../../../../utils/azureClients"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { - AbstractServerCreate, - PostgresServerType, -} from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { Progress } from 'vscode'; +import { ext } from '../../../../extensionVariables'; +import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; + public priority: number = 150; - public async execute( - context: IPostgresServerWizardContext, - progress: Progress<{ message?: string; increment?: number }> - ): Promise { - const locationName: string = ( - await LocationListStep.getLocation(context) - ).name; - const rgName: string = nonNullProp( - nonNullProp(context, "resourceGroup"), - "name" - ); - const size: string = nonNullProp(nonNullProp(context, "sku"), "size"); - const newServerName = nonNullProp(context, "newServerName"); - const password: string = nonNullProp(context, "adminPassword"); + public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - return await callWithMaskHandling(async () => { - const serverType = nonNullProp(context, "serverType"); - const createMessage: string = localize( - "creatingPostgresServer", - 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', - context.newServerName - ); + const locationName: string = (await LocationListStep.getLocation(context)).name; + const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); + const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); + const newServerName = nonNullProp(context, 'newServerName'); + const password: string = nonNullProp(context, 'adminPassword'); - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, "sku"), - administratorLogin: nonNullProp(context, "shortUserName"), - administratorLoginPassword: password, - size: parseInt(size), - }; + return await callWithMaskHandling( + async () => { + const serverType = nonNullProp(context, 'serverType'); + const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = - await createPostgreSQLClient(context); - context.server = - await singleClient.servers.beginCreateAndWait( - rgName, - newServerName, - this.asSingleParameters(options) - ); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = - await createPostgreSQLFlexibleClient(context); - context.server = - await flexiClient.servers.beginCreateAndWait( - rgName, - newServerName, - this.asFlexibleParameters(options) - ); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, password); - } + ext.outputChannel.appendLog(createMessage); + progress.report({ message: createMessage }); + const options: AbstractServerCreate = { + location: locationName, + sku: nonNullProp(context, 'sku'), + administratorLogin: nonNullProp(context, 'shortUserName'), + administratorLoginPassword: password, + size: parseInt(size) + }; - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } + switch (serverType) { + case PostgresServerType.Single: + const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); + context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); + break; + case PostgresServerType.Flexible: + const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); + context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); + break; + } + context.server.serverType = serverType; + context.activityResult = context.server as AppResource; + }, + password); + } - private asFlexibleParameters( - parameters: AbstractServerCreate - ): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size, - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier, - }, - }; - } + public shouldExecute(context: IPostgresServerWizardContext): boolean { + return !context.server; + } + + + private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { + return { + location: parameters.location, + version: "12", + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + storage: { + storageSizeGB: parameters.size + }, + sku: { + name: parameters.sku.name, + tier: parameters.sku.tier + }, + } + } + + private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { + return { + location: parameters.location, + sku: { + name: parameters.sku.name, + capacity: parameters.sku.capacity, + size: parameters.sku.size, + family: parameters.sku.family, + tier: parameters.sku.tier as SingleModels.SkuTier + }, + properties: { + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + sslEnforcement: "Enabled", + createMode: "Default", + version: "11", + storageProfile: { + storageMB: parameters.size + } + } + } + } - private asSingleParameters( - parameters: AbstractServerCreate - ): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier, - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: - parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size, - }, - }, - }; - } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts index dd5c84c25..c48d40c37 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts @@ -3,66 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; -const pwConditionMsg = localize( - "passwordConditionMsg", - "Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.)." -); +const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, "shortUserName"); - context.adminPassword = await context.ui.showInputBox({ - placeHolder: localize("pwPlaceholder", "Administrator Password"), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => - validatePassword(user, password), - }); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const user = nonNullProp(context, 'shortUserName'); + context.adminPassword = (await context.ui.showInputBox({ + placeHolder: localize('pwPlaceholder', 'Administrator Password'), + prompt: pwConditionMsg, + password: true, + validateInput: (password: string) => validatePassword(user, password), + })); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.adminPassword; + } } -async function validatePassword( - username: string, - password: string -): Promise { - password = password ? password : ""; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map((substring) => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize( - "pwLengthCheck", - "Password must be between {0} and {1} characters.", - min, - max - ); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize( - "pwUserSimalarityCheck", - "Password cannot contain the username." - ); - } else { - return undefined; - } +async function validatePassword(username: string, password: string): Promise { + password = password ? password : ''; + + const min = 8; + const max = 128; + + const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; + let numOccurrence = 0; + + regex.map(substring => { + if (password.match(substring)) { + numOccurrence++; + } + }); + + if (password.length < min || password.length > max) { + return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); + } else if (numOccurrence < 3) { + return pwConditionMsg; + } else if (password.includes(username)) { + return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts index 14b7de8f7..7b4890d07 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts @@ -3,80 +3,46 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = ( - await context.ui.showInputBox({ - placeHolder: localize( - "usernamePlaceholder", - "Administrator Username" - ), - validateInput: validateUser, - }) - ).trim(); - const usernameSuffix: string = `@${nonNullProp( - context, - "newServerName" - )}`; - context.longUserName = context.shortUserName + usernameSuffix; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + context.shortUserName = (await context.ui.showInputBox({ + placeHolder: localize('usernamePlaceholder', 'Administrator Username'), + validateInput: validateUser, + })).trim(); + const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; + context.longUserName = context.shortUserName + usernameSuffix; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.shortUserName; + } } async function validateUser(username: string): Promise { - username = username ? username.trim() : ""; + username = username ? username.trim() : ''; - const min = 1; - const max = 63; + const min = 1; + const max = 63; - const restricted = [ - "azure_superuser", - "azure_pg_admin", - "admin", - "administrator", - "root", - "guest", - "public", - ]; + const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; - if (username.length < min || username.length > max) { - return localize( - "usernameLenghtMatch", - "The name must be between {0} and {1} characters.", - min, - max - ); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize( - "usernameCharacterCheck", - 'The name can only contain letters, numbers, and the "_" character.' - ); - } else if (username.match(/^[0-9]+/)) { - return localize( - "usernameBeginningMatch", - "The name cannot start with a number." - ); - } else if (username.toLowerCase().startsWith("pg_")) { - return localize( - "usernameStartWithCheck", - 'Admin username cannot start with "pg_".' - ); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map((d) => `"${d}"`).join(", "); - return localize( - "usernameRestrictedCheck", - "Admin username cannot be any of the following: {0}.", - restrictedString - ); - } else { - return undefined; - } + if (username.length < min || username.length > max) { + return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); + } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { + return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); + } else if (username.match(/^[0-9]+/)) { + return localize('usernameBeginningMatch', 'The name cannot start with a number.'); + } else if (username.toLowerCase().startsWith('pg_')) { + return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); + } else if (restricted.includes(username.toLowerCase())) { + const restrictedString = restricted.map(d => `"${d}"`).join(', '); + return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts index 76b25373e..1af03f5c7 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts @@ -3,111 +3,58 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ResourceGroupListStep, - resourceGroupNamingRules, -} from "@microsoft/vscode-azext-azureutils"; -import { AzureNameStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { - AbstractPostgresClient, - createAbstractPostgresClient, -} from "../../../abstract/AbstractPostgresClient"; -import { - AbstractNameAvailability, - PostgresServerType, -} from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; +import { AzureNameStep } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; +import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerNameStep extends AzureNameStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient( - nonNullProp(context, "serverType"), - context - ); - context.newServerName = ( - await context.ui.showInputBox({ - placeHolder: localize("serverNamePlaceholder", "Server name"), - prompt: localize( - "enterServerNamePrompt", - "Provide a name for the PostgreSQL Server." - ), - validateInput: (name: string) => - validatePostgresServerName( - name, - client, - nonNullProp(context, "serverType") - ), - }) - ).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName( - context, - context.newServerName, - resourceGroupNamingRules - ); - } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable( - context: IPostgresServerWizardContext, - name: string - ): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); + context.newServerName = (await context.ui.showInputBox({ + placeHolder: localize('serverNamePlaceholder', 'Server name'), + prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), + validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) + })).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.newServerName; + } + + protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validatePostgresServerName( - name: string, - client: AbstractPostgresClient, - serverType: PostgresServerType -): Promise { - name = name ? name.trim() : ""; +async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { + name = name ? name.trim() : ''; + + const min = 3; + const max = 63; - const min = 3; - const max = 63; + if (name.length < min || name.length > max) { + return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); + } else if (!(/^[a-z0-9-]+$/).test(name)) { + return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); + } else if (name.startsWith('-') || name.endsWith('-')) { + return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); + } + const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; + const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); - if (name.length < min || name.length > max) { - return localize( - "serverNameLengthCheck", - "The name must be between {0} and {1} characters.", - min, - max - ); - } else if (!/^[a-z0-9-]+$/.test(name)) { - return localize( - "serverNameCharacterCheck", - "Server name must only contain lowercase letters, numbers, and hyphens." - ); - } else if (name.startsWith("-") || name.endsWith("-")) { - return localize( - "serverNamePrefixSuffixCheck", - "Server name must not start or end in a hyphen." - ); - } - const resourceType = - serverType === PostgresServerType.Single - ? "Microsoft.DBforPostgreSQL" - : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = - await client.checkNameAvailability.execute({ - name: name, - type: resourceType, - }); + if (!availability.nameAvailable) { + return availability.message ? + availability.message : + localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); + } - if (!availability.nameAvailable) { - return availability.message - ? availability.message - : localize( - "serverNameAvailabilityCheck", - 'Server name "{0}" is not available.', - name - ); - } + return undefined; - return undefined; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts index e93027936..3431e8f00 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts @@ -3,60 +3,44 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { Progress } from "vscode"; -import { ext } from "../../../../extensionVariables"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { - PostgresAbstractServer, - PostgresServerType, -} from "../../../abstract/models"; -import { setPostgresCredentials } from "../../setPostgresCredentials"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { Progress } from 'vscode'; +import { ext } from '../../../../extensionVariables'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; +import { setPostgresCredentials } from '../../setPostgresCredentials'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; + public priority: number = 200; - public async execute( - context: IPostgresServerWizardContext, - progress: Progress<{ message?: string; increment?: number }> - ): Promise { - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if ( - context.serverType && - context.serverType === PostgresServerType.Single - ) { - user = nonNullProp(context, "longUserName"); - } else { - user = nonNullProp(context, "shortUserName"); - } - const newServerName: string = nonNullProp(context, "newServerName"); + public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const setupMessage: string = localize( - "setupCredentialsMessage", - 'Setting up Credentials for server "{0}"...', - newServerName - ); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, "adminPassword"); - const server: PostgresAbstractServer = nonNullProp(context, "server"); + let user: string; + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexbile Server instance + if (context.serverType && context.serverType === PostgresServerType.Single) { + user = nonNullProp(context, 'longUserName'); + } else { + user = nonNullProp(context, 'shortUserName'); + } + const newServerName: string = nonNullProp(context, 'newServerName'); - await setPostgresCredentials(user, password, nonNullProp(server, "id")); - const completedMessage: string = localize( - "addedCredentialsMessage", - 'Successfully setup credentials for server "{0}".', - newServerName - ); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } + const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); + progress.report({ message: setupMessage }); + ext.outputChannel.appendLog(setupMessage); + const password: string = nonNullProp(context, 'adminPassword'); + const server: PostgresAbstractServer = nonNullProp(context, 'server'); - public shouldExecute(): boolean { - return true; - } + await setPostgresCredentials(user, password, nonNullProp(server, 'id')); + const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + } + + public shouldExecute(): boolean { + return true; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts index 3efe5e223..654cd0430 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts @@ -2,10 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzureWizardPromptStep, - IAzureQuickPickItem, -} from "@microsoft/vscode-azext-utils"; +import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../utils/localize"; import { nonNullProp } from "../../../../utils/nonNull"; import { openUrl } from "../../../../utils/openUrl"; @@ -13,257 +10,241 @@ import { AbstractSku, PostgresServerType } from "../../../abstract/models"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; + label: string; + description: string; + sku: AbstractSku; + group?: string; } export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = - await this.getPicks(nonNullProp(context, "serverType")); - pricingTiers.push({ - label: localize( - "ShowPricingCalculator", - "$(link-external) Show pricing information..." - ), - onPicked: async () => { - await openUrl("https://aka.ms/AAcxhvm"); - }, - data: undefined, - }); + public async prompt( + context: IPostgresServerWizardContext + ): Promise { + const placeHolder: string = localize( + "selectPostgresSku", + "Select the Postgres SKU and options." + ); + const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); + pricingTiers.push({ + label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), + onPicked: async () => { + await openUrl('https://aka.ms/AAcxhvm'); + }, data: undefined + }); - context.sku = ( - await context.ui.showQuickPick(pricingTiers, { - placeHolder, - suppressPersistence: true, - enableGrouping: true, - }) - ).data; - } + context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return context.sku === undefined; + } - public async getPicks( - serverType: PostgresServerType - ): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = - serverType === PostgresServerType.Single - ? singleServerSkus - : flexibleServerSkus; + public async getPicks(serverType: PostgresServerType): Promise[]> { + const options: IAzureQuickPickItem[] = []; + const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: - option.group || - localize("addlOptions", "Additional Options"), - }); - }); - return options; - } + skuOptions.forEach((option) => { + options.push({ + label: option.label, + description: localize( + nonNullProp(option.sku, "name"), + option.description + ), + data: option.sku, + group: option.group || localize('addlOptions', 'Additional Options') + }); + }); + return options; + } } -const recommendedGroup = localize("recommendGroup", "Recommended"); +const recommendedGroup = localize('recommendGroup', 'Recommended'); const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup, - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup, - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, + { + label: "B1", + description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", + sku: { + name: "B_Gen5_1", + tier: "Basic", + capacity: 1, + family: "Gen5", + size: "5120", + }, + group: recommendedGroup + }, + { + label: "B2", + description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", + sku: { + name: "B_Gen5_2", + tier: "Basic", + capacity: 2, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP2", + description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_2", + tier: "GeneralPurpose", + capacity: 2, + family: "Gen5", + size: "51200", + }, + group: recommendedGroup + }, + { + label: "GP4", + description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_4", + tier: "GeneralPurpose", + capacity: 4, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP8", + description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_8", + tier: "GeneralPurpose", + capacity: 8, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP16", + description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_16", + tier: "GeneralPurpose", + capacity: 16, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP32", + description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_32", + tier: "GeneralPurpose", + capacity: 32, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP64", + description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_64", + tier: "GeneralPurpose", + capacity: 64, + family: "Gen5", + size: "204800", + }, + }, ]; // Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 // See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup, - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup, - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, + { + label: "B1ms", + description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", + sku: { + name: "Standard_B1ms", + tier: "Burstable", + capacity: 1, + size: "32", + }, + group: recommendedGroup + }, + { + label: "B2s", + description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", + sku: { + name: "Standard_B2s", + tier: "Burstable", + capacity: 2, + size: "32", + }, + }, + { + label: "D2s_v3", + description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", + sku: { + name: "Standard_D2s_v3", + tier: "GeneralPurpose", + capacity: 2, + size: "32", + }, + group: recommendedGroup + }, + { + label: "D4s_v3", + description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", + sku: { + name: "Standard_D4s_v3", + tier: "GeneralPurpose", + capacity: 4, + size: "32", + }, + }, + { + label: "D8s_v3", + description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", + sku: { + name: "Standard_D8s_v3", + tier: "GeneralPurpose", + capacity: 8, + size: "64", + }, + }, + { + label: "D16s_v3", + description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", + sku: { + name: "Standard_D16s_v3", + tier: "GeneralPurpose", + capacity: 16, + size: "64", + }, + }, + { + label: "D32s_v3", + description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", + sku: { + name: "Standard_D32s_v3", + tier: "GeneralPurpose", + capacity: 32, + size: "64", + }, + }, + { + label: "D48s_v3", + description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", + sku: { + name: "Standard_D48s_v3", + tier: "GeneralPurpose", + capacity: 48, + size: "256", + }, + }, + { + label: "D64s_v3", + description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", + sku: { + name: "Standard_D64s_v3", + tier: "GeneralPurpose", + capacity: 64, + size: "256", + }, + }, ]; diff --git a/Source/postgres/commands/deletePostgresDatabase.ts b/Source/postgres/commands/deletePostgresDatabase.ts index 705b8823f..a09520bde 100644 --- a/Source/postgres/commands/deletePostgresDatabase.ts +++ b/Source/postgres/commands/deletePostgresDatabase.ts @@ -3,51 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function deletePostgresDatabase( - context: IActionContext, - node?: PostgresDatabaseTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } - const message: string = localize( - "deletesPostgresDatabase", - 'Are you sure you want to delete database "{0}"?', - node.databaseName - ); - const result = await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresDatabase" }, - DialogResponses.deleteResponse - ); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize( - "deletePostgresDatabaseMsg", - 'Successfully deleted database "{0}".', - node.databaseName - ); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } + const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); + const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); + if (result === DialogResponses.deleteResponse) { + await node.deleteTreeItem(context); + } + const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresFunction.ts b/Source/postgres/commands/deletePostgresFunction.ts index 9ee7a21d7..9a4547428 100644 --- a/Source/postgres/commands/deletePostgresFunction.ts +++ b/Source/postgres/commands/deletePostgresFunction.ts @@ -3,50 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { window } from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import { window } from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function deletePostgresFunction( - context: IActionContext, - treeItem?: PostgresFunctionTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - { ...context, suppressCreatePick: true }, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresFunctionTreeItem.contextValue, - } - ); - } +export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresFunctionTreeItem.contextValue + }); + } - const message: string = localize( - "deleteFunction", - 'Are you sure you want to delete function "{0}"?', - treeItem.label - ); - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresFunction" }, - DialogResponses.deleteResponse - ); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize( - "successfullyDeletedFunction", - 'Successfully deleted function "{0}".', - treeItem.label - ); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresServer.ts b/Source/postgres/commands/deletePostgresServer.ts index 686b3c134..733c6fca6 100644 --- a/Source/postgres/commands/deletePostgresServer.ts +++ b/Source/postgres/commands/deletePostgresServer.ts @@ -3,29 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { deleteDatabaseAccount } from "../../commands/deleteDatabaseAccount/deleteDatabaseAccount"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; +import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; +import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -export async function deletePostgresServer( - context: IActionContext, - node?: PostgresServerTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } +export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } - await deleteDatabaseAccount(context, node, true); + await deleteDatabaseAccount(context, node, true) } diff --git a/Source/postgres/commands/deletePostgresStoredProcedure.ts b/Source/postgres/commands/deletePostgresStoredProcedure.ts index 244a207d2..6abece79b 100644 --- a/Source/postgres/commands/deletePostgresStoredProcedure.ts +++ b/Source/postgres/commands/deletePostgresStoredProcedure.ts @@ -3,51 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { window } from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import { window } from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; +import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; -export async function deletePostgresStoredProcedure( - context: IActionContext, - treeItem?: PostgresStoredProcedureTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = - await ext.rgApi.pickAppResource( - { ...context, suppressCreatePick: true }, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresStoredProcedureTreeItem.contextValue, - } - ); - } +export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue + }); + } - const message: string = localize( - "deleteStoredProcedure", - 'Are you sure you want to delete stored procedure "{0}"?', - treeItem.label - ); - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresStoredProcedure" }, - DialogResponses.deleteResponse - ); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize( - "successfullyDeletedStoredProcedure", - 'Successfully deleted stored procedure "{0}".', - treeItem.label - ); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresTable.ts b/Source/postgres/commands/deletePostgresTable.ts index 60cfb0c18..bfdce33a2 100644 --- a/Source/postgres/commands/deletePostgresTable.ts +++ b/Source/postgres/commands/deletePostgresTable.ts @@ -3,48 +3,26 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { window } from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import { window } from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; -export async function deletePostgresTable( - context: IActionContext, - node?: PostgresTableTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource( - { ...context, suppressCreatePick: true }, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue, - } - ); - } - const message: string = localize( - "deletesPostgresTable", - 'Are you sure you want to delete table "{0}"?', - node.label - ); - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresTable" }, - DialogResponses.deleteResponse - ); - await node.deleteTreeItem(context); - const deleteMessage: string = localize( - "successfullyDeletedTable", - 'Successfully deleted table "{0}".', - node.label - ); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresTableTreeItem.contextValue + }); + } + const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); + await node.deleteTreeItem(context); + const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/enterPostgresCredentials.ts b/Source/postgres/commands/enterPostgresCredentials.ts index ff146d290..aa993c337 100644 --- a/Source/postgres/commands/enterPostgresCredentials.ts +++ b/Source/postgres/commands/enterPostgresCredentials.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; +import * as vscode from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { PostgresServerType } from "../abstract/models"; +import { nonNullProp } from '../../utils/nonNull'; +import { PostgresServerType } from '../abstract/models'; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; import { setPostgresCredentials } from "./setPostgresCredentials"; @@ -17,118 +17,69 @@ import { setPostgresCredentials } from "./setPostgresCredentials"; * Get the username and password for the Postgres database from user input. */ async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string; password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize( - "enterUsername", - 'Enter username for server "{0}"', - serverDisplayName - ), - stepName: "enterPostgresUsername", - validateInput: (value: string) => { - return value && value.length - ? undefined - : localize( - "usernameCannotBeEmpty", - "Username cannot be empty." - ); - }, - }); + context: IActionContext, + serverType: PostgresServerType, + serverName: string, + serverDisplayName: string +): Promise<{ username: string, password: string }> { + let username: string = await context.ui.showInputBox({ + prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), + stepName: 'enterPostgresUsername', + validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } + }); - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if ( - serverType === PostgresServerType.Single && - !username.includes(usernameSuffix) - ) { - username += usernameSuffix; - } + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexible Server instance + const usernameSuffix: string = `@${serverName}`; + if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { + username += usernameSuffix; + } - const password: string = await context.ui.showInputBox({ - prompt: localize( - "enterPassword", - 'Enter password for server "{0}"', - serverDisplayName - ), - stepName: "enterPostgresPassword", - password: true, - validateInput: (value: string) => { - return value && value.length - ? undefined - : localize( - "passwordCannotBeEmpty", - "Password cannot be empty." - ); - }, - }); + const password: string = await context.ui.showInputBox({ + prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), + stepName: 'enterPostgresPassword', + password: true, + validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } + }); - return { username, password }; + return { username, password }; } /** * Save the username and password in secure local storage. */ -async function persistUsernamePassword( - id: string, - serverName: string, - username: string, - password: string -): Promise { - const progressMessage: string = localize( - "setupCredentialsMessage", - 'Setting up credentials for server "{0}"...', - serverName - ); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage, - }; +async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { + const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage + }; - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); + await vscode.window.withProgress(options, async () => { + await setPostgresCredentials(username, password, id); + }); - const completedMessage: string = localize( - "setupCredentialsMessage", - 'Successfully added credentials to server "{0}".', - serverName - ); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); + const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); } -export async function enterPostgresCredentials( - context: IActionContext, - treeItem?: PostgresServerTreeItem -): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } +export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, "azureName"); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, "id"); + const serverType = treeItem.serverType; + const serverName: string = nonNullProp(treeItem, 'azureName'); + const serverDisplayName: string = treeItem.label; + const id: string = nonNullProp(treeItem, 'id'); - const { username, password } = await getUsernamePassword( - context, - serverType, - serverName, - serverDisplayName - ); + const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); - await persistUsernamePassword(id, serverName, username, password); + await persistUsernamePassword(id, serverName, username, password); - treeItem.setCredentials(username, password); - await treeItem.refresh(context); + treeItem.setCredentials(username, password); + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/executePostgresQueryInDocument.ts b/Source/postgres/commands/executePostgresQueryInDocument.ts index 4aedb847b..af5d3ca5e 100644 --- a/Source/postgres/commands/executePostgresQueryInDocument.ts +++ b/Source/postgres/commands/executePostgresQueryInDocument.ts @@ -3,92 +3,63 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { EOL } from "os"; -import * as path from "path"; -import { ClientConfig, QueryResult } from "pg"; -import * as vscode from "vscode"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import * as vscodeUtil from "../../utils/vscodeUtils"; -import { runPostgresQuery } from "../runPostgresQuery"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { checkAuthentication } from "./checkAuthentication"; -import { loadPersistedPostgresDatabase } from "./registerPostgresCommands"; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import { EOL } from 'os'; +import * as path from 'path'; +import { ClientConfig, QueryResult } from 'pg'; +import * as vscode from 'vscode'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import * as vscodeUtil from '../../utils/vscodeUtils'; +import { runPostgresQuery } from '../runPostgresQuery'; +import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; +import { checkAuthentication } from './checkAuthentication'; +import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; -export async function executePostgresQueryInDocument( - context: IActionContext -): Promise { - await loadPersistedPostgresDatabase(); +export async function executePostgresQueryInDocument(context: IActionContext): Promise { + await loadPersistedPostgresDatabase(); - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } + let treeItem: PostgresDatabaseTreeItem; + if (ext.connectedPostgresDB) { + treeItem = ext.connectedPostgresDB; + } else { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } - const clientConfig: ClientConfig = await checkAuthentication( - context, - treeItem - ); + const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); - const activeEditor: vscode.TextEditor | undefined = - vscode.window.activeTextEditor; + const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - if (!activeEditor?.document) { - throw new Error( - localize( - "openQueryBeforeExecuting", - "Open a PostgreSQL query before executing." - ) - ); - } + if (!activeEditor?.document) { + throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); + } - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery( - clientConfig, - query - ); - ext.outputChannel.appendLine( - localize( - "executedQuery", - 'Successfully executed "{0}" query.', - queryResult.command - ) - ); + const query: string | undefined = activeEditor.document.getText(); + const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); + ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); - if (queryResult.rowCount) { - const fileExtension: string = path.extname( - activeEditor.document.fileName - ); - const queryFileName: string = path.basename( - activeEditor.document.fileName, - fileExtension - ); - const outputFileName: string = `${queryFileName}-output`; + if (queryResult.rowCount) { + const fileExtension: string = path.extname(activeEditor.document.fileName); + const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); + const outputFileName: string = `${queryFileName}-output`; - const fields: string[] = queryResult.fields.map((f) => f.name); - let csvData: string = `${fields.join(",")}${EOL}`; + const fields: string[] = queryResult.fields.map(f => f.name); + let csvData: string = `${fields.join(',')}${EOL}`; - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(",")}${EOL}`; - } + for (const row of queryResult.rows) { + const fieldValues: string[] = []; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + fieldValues.push(row[field]); + } + csvData += `${fieldValues.join(',')}${EOL}`; + } - await vscodeUtil.showNewFile(csvData, outputFileName, ".csv"); - } - await treeItem.refresh(context); + await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); + } + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/openPostgresFunction.ts b/Source/postgres/commands/openPostgresFunction.ts index 4b186ed71..26103970f 100644 --- a/Source/postgres/commands/openPostgresFunction.ts +++ b/Source/postgres/commands/openPostgresFunction.ts @@ -9,20 +9,13 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function openPostgresFunction( - context: IActionContext, - treeItem?: PostgresFunctionTreeItem -): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresFunctionTreeItem.contextValue, - } - ); - } +export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresFunctionTreeItem.contextValue + }); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/openPostgresStoredProcedure.ts b/Source/postgres/commands/openPostgresStoredProcedure.ts index 1eb8931aa..3c98ff743 100644 --- a/Source/postgres/commands/openPostgresStoredProcedure.ts +++ b/Source/postgres/commands/openPostgresStoredProcedure.ts @@ -9,21 +9,13 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function openPostgresStoredProcedure( - context: IActionContext, - treeItem?: PostgresStoredProcedureTreeItem -): Promise { - if (!treeItem) { - treeItem = - await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresStoredProcedureTreeItem.contextValue, - } - ); - } +export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue + }); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/registerPostgresCommands.ts b/Source/postgres/commands/registerPostgresCommands.ts index 89412a2ba..b861e00f7 100644 --- a/Source/postgres/commands/registerPostgresCommands.ts +++ b/Source/postgres/commands/registerPostgresCommands.ts @@ -3,19 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, - registerCommandWithTreeNodeUnwrapping, -} from "@microsoft/vscode-azext-utils"; +import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; import { defaults } from "pg"; import { languages } from "vscode"; -import { - connectedPostgresKey, - doubleClickDebounceDelay, - postgresDefaultDatabase, - postgresLanguageId, -} from "../../constants"; +import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; import { ext } from "../../extensionVariables"; import { openUrl } from "../../utils/openUrl"; import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; @@ -37,126 +28,55 @@ import { openPostgresFunction } from "./openPostgresFunction"; import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push( - languages.registerCodeLensProvider( - postgresLanguageId, - ext.postgresCodeLensProvider - ) - ); + ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); + ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); - void loadPersistedPostgresDatabase(); + void loadPersistedPostgresDatabase(); - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; + //update defaults.database of 'pg' + defaults.database = postgresDefaultDatabase; - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteServer", - deletePostgresServer - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.enterCredentials", - enterPostgresCredentials - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.configureFirewall", - configurePostgresFirewall - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.createDatabase", - createPostgresDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteDatabase", - deletePostgresDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteTable", - deletePostgresTable - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.openFunction", - openPostgresFunction, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.openStoredProcedure", - openPostgresStoredProcedure, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteFunction", - deletePostgresFunction - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteStoredProcedure", - deletePostgresStoredProcedure - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.connectDatabase", - connectPostgresDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.createFunctionQuery", - createPostgresFunctionQuery - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.createStoredProcedureQuery", - createPostgresStoredProcedureQuery - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.executeQuery", - executePostgresQueryInDocument - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.copyConnectionString", - copyConnectionString - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.showPasswordlessWiki", - showPasswordlessWiki - ); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); + registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); + registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); + registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); + registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); + registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); + registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); + registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); + registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); + registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); + registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); } export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling( - "postgreSQL.loadPersistedDatabase", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = "true"; + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = 'true'; - try { - const persistedTreeItemId: string | undefined = - ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: - | PostgresDatabaseTreeItem - | undefined = ( - await ext.rgApi.appResourceTree.findTreeItem( - persistedTreeItemId, - context - ) - ); - if (persistedTreeItem) { - await connectPostgresDatabase( - context, - persistedTreeItem - ); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase( - undefined - ); - } - } - } - ); + try { + const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); + if (persistedTreeItemId) { + const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); + if (persistedTreeItem) { + await connectPostgresDatabase(context, persistedTreeItem); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(undefined); + } + } + }); } export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); + await openUrl("https://aka.ms/postgresql-passwordless-wiki"); } diff --git a/Source/postgres/commands/setPostgresCredentials.ts b/Source/postgres/commands/setPostgresCredentials.ts index 2807acc3c..8df8260f6 100644 --- a/Source/postgres/commands/setPostgresCredentials.ts +++ b/Source/postgres/commands/setPostgresCredentials.ts @@ -8,37 +8,25 @@ import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } -export async function setPostgresCredentials( - username: string, - password: string, - serverId: string -): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = - ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue - ? JSON.parse(storedValue) - : []; +export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { - return server.id !== serverId; - }); + // Remove this server from the cache if it's there + servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); - const newServer: IPersistedServer = { - id: serverId, - username, - }; + const newServer: IPersistedServer = { + id: serverId, + username + }; - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store( - getSecretStorageKey(serviceName, serverId), - password - ); + servers.push(newServer); + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); } diff --git a/Source/postgres/getClientConfig.ts b/Source/postgres/getClientConfig.ts index 431a95bea..bdc545945 100644 --- a/Source/postgres/getClientConfig.ts +++ b/Source/postgres/getClientConfig.ts @@ -8,15 +8,12 @@ import { ConnectionOptions } from "tls"; import { postgresDefaultPort } from "../constants"; import { nonNullProp } from "../utils/nonNull"; import { PostgresServerType } from "./abstract/models"; -import { - ParsedPostgresConnectionString, - addDatabaseToConnectionString, -} from "./postgresConnectionStrings"; +import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; + password: ClientConfig | undefined; + azureAd: ClientConfig | undefined; + connectionString: ClientConfig | undefined; }; export type PostgresClientConfigType = keyof PostgresClientConfigs; @@ -24,133 +21,82 @@ export type PostgresClientConfigType = keyof PostgresClientConfigs; * Test if the database can be connected to using the given client config. * @throws if the client failed to connect to the database. */ -export async function testClientConfig( - clientConfig: ClientConfig -): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } +export async function testClientConfig(clientConfig: ClientConfig): Promise { + const client = new Client(clientConfig); + try { + await client.connect(); + } finally { + await client.end(); + } } -async function getConnectionStringClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - databaseName: string -): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString( - connectionString, - databaseName - ); - } - return { connectionString: connectionString }; +async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { + let connectionString = parsedConnectionString.connectionString; + if (!parsedConnectionString.databaseName) { + connectionString = addDatabaseToConnectionString(connectionString, databaseName); + } + return { connectionString: connectionString }; } -async function getUsernamePasswordClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string -): Promise { - const host = nonNullProp(parsedConnectionString, "hostName"); - const port: number = parsedConnectionString.port - ? parseInt(parsedConnectionString.port) - : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; +async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { + const host = nonNullProp(parsedConnectionString, 'hostName'); + const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); + const username: string | undefined = parsedConnectionString.username; + const password: string | undefined = parsedConnectionString.password; - if (!!username && !!password && !!host && !!port) { - return { - user: username, - password, - ssl: sslAzure, - host, - port, - database: databaseName, - }; - } else { - return undefined; - } + if (!!username && !!password && !!host && !!port) { + return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; + } else { + return undefined; + } } async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string, + azureAdUserId: string, + getToken: () => Promise ): Promise { - const host = nonNullProp(parsedConnectionString, "hostName"); - const port: number = parsedConnectionString.port - ? parseInt(parsedConnectionString.port) - : parseInt(postgresDefaultPort); - return { - user: azureAdUserId, - password: getToken, - ssl: sslAzure, - host, - port, - database: databaseName, - }; + const host = nonNullProp(parsedConnectionString, 'hostName'); + const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); + return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; } export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + serverType: PostgresServerType, + hasSubscription: boolean, + databaseName: string, + azureUserId?: string, + getToken?: () => Promise ): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined, - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: - serverType === PostgresServerType.Single - ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] - : [DigiCertGlobalRootCA], - }; - const passwordClientConfig = await getUsernamePasswordClientConfig( - parsedConnectionString, - sslAzure, - databaseName - ); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if ( - serverType === PostgresServerType.Flexible && - !!azureUserId && - !!getToken - ) { - const azureAdClientConfig = await getAzureAdClientConfig( - parsedConnectionString, - sslAzure, - databaseName, - azureUserId, - getToken - ); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = - await getConnectionStringClientConfig( - parsedConnectionString, - databaseName - ); - clientConfigs.connectionString = connectionStringClientConfig; - } + const clientConfigs: PostgresClientConfigs = { + password: undefined, + azureAd: undefined, + connectionString: undefined + }; + if (hasSubscription) { + const sslAzure: ConnectionOptions = { + // Always provide the certificate since it is accepted even when SSL is disabled + // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) + // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 + ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] + }; + const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); + if (passwordClientConfig) { + clientConfigs.password = passwordClientConfig; + } + if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { + const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); + clientConfigs.azureAd = azureAdClientConfig; + } + } else { + const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); + clientConfigs.connectionString = connectionStringClientConfig; + } - return clientConfigs; + return clientConfigs; } // Postgres Single Server Root Cert, https://aka.ms/AA7wnvl @@ -223,3 +169,4 @@ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE-----`; + diff --git a/Source/postgres/getPostgresProcedureQueryRows.ts b/Source/postgres/getPostgresProcedureQueryRows.ts index 0cecca979..ad791ff2e 100644 --- a/Source/postgres/getPostgresProcedureQueryRows.ts +++ b/Source/postgres/getPostgresProcedureQueryRows.ts @@ -9,16 +9,16 @@ import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; + schema: string; + name: string; + oid: number; + args: string; + definition: string; } function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, + // Adapted from https://aka.ms/AA83fg8 + return `select n.nspname as schema, p.proname as name, p.oid as oid, pg_get_function_arguments(p.oid) as args, @@ -33,37 +33,26 @@ function getProceduresQuery(conditions: string): string { order by name;`; } -export async function getPostgresProcedureQueryRows( - treeItem: PostgresResourcesTreeItemBase -): Promise { - let conditions: string; +export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { + let conditions: string; - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${ - (await treeItem.parent.parent.supportsStoredProcedures( - treeItem.clientConfig - )) - ? "and p.prokind = 'f'" - : "" - }`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } + if (treeItem instanceof PostgresFunctionsTreeItem) { + conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') + ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; + } else { + // Assume stored procedures + conditions = "and p.prokind = 'p'"; + } - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery( - treeItem.clientConfig, - query - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; + const query: string = getProceduresQuery(conditions); + const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } + treeItem.resourcesAndSchemas = {}; + for (const row of rows) { + treeItem.addResourcesAndSchemasEntry(row.name, row.schema); + } - return rows; + return rows; } diff --git a/Source/postgres/getTables.ts b/Source/postgres/getTables.ts index e74d1074d..ebc7d1c75 100644 --- a/Source/postgres/getTables.ts +++ b/Source/postgres/getTables.ts @@ -7,10 +7,10 @@ import { ClientConfig, QueryResult } from "pg"; import { runPostgresQuery } from "./runPostgresQuery"; export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; + schemaName: string; + name: string; + oid: string; + columnNames: string[]; } const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, @@ -23,22 +23,12 @@ const tablesQuery: string = `select schemaname, tablename, array_agg (columnname where schemaname != 'pg_catalog' AND schemaname != 'information_schema' group by schemaname, tablename;`; -export async function getTables( - clientConfig: ClientConfig -): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery( - clientConfig, - tablesQuery - ); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ - schemaName: row.schemaname, - name: row.tablename, - oid: row.oid, - columnNames: row.columnnames, - }); - } - return tablesArray; +export async function getTables(clientConfig: ClientConfig): Promise { + const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); + const tablesArray: IPostgresTable[] = []; + for (const row of tableInfoRows.rows) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); + } + return tablesArray; } diff --git a/Source/postgres/postgresConnectionStrings.ts b/Source/postgres/postgresConnectionStrings.ts index f1c46e6e7..ea9ce9e2e 100644 --- a/Source/postgres/postgresConnectionStrings.ts +++ b/Source/postgres/postgresConnectionStrings.ts @@ -8,84 +8,67 @@ import { postgresDefaultPort } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; import { nonNullProp } from "../utils/nonNull"; -export function parsePostgresConnectionString( - connectionString: string -): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); +export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { + const config: ConnectionOptions = parse(connectionString.trim()); + return new ParsedPostgresConnectionString(connectionString, config); } -export function addDatabaseToConnectionString( - connectionString: string, - databaseName: string -): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); +export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { + const url = new URL(connectionString); + url.pathname = encodeURIComponent(databaseName); + return url.toString(); } -export function createPostgresConnectionString( - hostName: string, - port: string = postgresDefaultPort, - username?: string | undefined, - password?: string | undefined, - databaseName?: string | undefined -): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + connectionString += `${encodedUsername}:${encodedPassword}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } -export function copyPostgresConnectionString( - hostName: string, - port: string = postgresDefaultPort, - username?: string | undefined, - password?: string | undefined, - databaseName?: string | undefined -): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; + connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; + public readonly hostName: string; + public username: string | undefined; + public password: string | undefined; + public readonly port: string; - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, "host"); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } + constructor(connectionString: string, config: ConnectionOptions) { + super(connectionString, config.database ? config.database : undefined); + this.hostName = nonNullProp(config, 'host'); + this.port = config.port ? config.port : `${postgresDefaultPort}`; + this.username = config.user; + this.password = config.password; + } } diff --git a/Source/postgres/postgresConstants.ts b/Source/postgres/postgresConstants.ts index f94f58a25..9bcf15144 100644 --- a/Source/postgres/postgresConstants.ts +++ b/Source/postgres/postgresConstants.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const invalidCredentialsErrorType: string = "28P01"; -export const firewallNotConfiguredErrorType: string = "28000"; -export const timeoutErrorType = "ETIMEDOUT"; +export const invalidCredentialsErrorType: string = '28P01'; +export const firewallNotConfiguredErrorType: string = '28000'; +export const timeoutErrorType = 'ETIMEDOUT'; diff --git a/Source/postgres/runPostgresQuery.ts b/Source/postgres/runPostgresQuery.ts index ce2a67c7b..b7d325364 100644 --- a/Source/postgres/runPostgresQuery.ts +++ b/Source/postgres/runPostgresQuery.ts @@ -5,18 +5,15 @@ import { Client, ClientConfig, QueryResult } from "pg"; -export async function runPostgresQuery( - clientConfig: ClientConfig, - query: string -): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } +export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { + const client: Client = new Client(clientConfig); + try { + await client.connect(); + return await client.query(query); + } finally { + await client.end(); + } } export function wrapArgInQuotes(input: string): string { - return `"${input}"`; + return `"${input}"`; } diff --git a/Source/postgres/services/PostgresCodeLensProvider.ts b/Source/postgres/services/PostgresCodeLensProvider.ts index d0d6bfe39..5d075eb3c 100644 --- a/Source/postgres/services/PostgresCodeLensProvider.ts +++ b/Source/postgres/services/PostgresCodeLensProvider.ts @@ -3,88 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { - CodeLens, - CodeLensProvider, - Event, - EventEmitter, - Position, - ProviderResult, - Range, -} from "vscode"; +import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; import { localize } from "../../utils/localize"; export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: EventEmitter = new EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling( - "postgreSQL.provideCodeLenses", - (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(): ProviderResult { + return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: CodeLens[] = []; - let title: string; - if (!isInitialized) { - title = localize("initializing", "Initializing..."); - } else if (isConnected) { - title = localize( - "connectedToDatabase", - 'Connected to "{0}"', - database - ); - } else { - title = localize( - "connectToDatabase", - "Connect to a database" - ); - } + let title: string; + if (!isInitialized) { + title = localize('initializing', 'Initializing...'); + } else if (isConnected) { + title = localize('connectedToDatabase', 'Connected to "{0}"', database); + } else { + title = localize('connectToDatabase', 'Connect to a database'); + } - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && "postgreSQL.connectDatabase", - }, - range: new Range(new Position(0, 0), new Position(0, 0)), - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title, + command: isInitialized && 'postgreSQL.connectDatabase' + }, + range: new Range(new Position(0, 0), new Position(0, 0)) + }); - if (isConnected) { - lenses.push({ - command: { - title: "Execute Query", - command: "postgreSQL.executeQuery", - }, - range: new Range( - new Position(0, 0), - new Position(0, 0) - ), - }); - } + if (isConnected) { + lenses.push({ + command: { + title: 'Execute Query', + command: 'postgreSQL.executeQuery' + }, + range: new Range(new Position(0, 0), new Position(0, 0)) + }); + } - return lenses; - } - ); - } + return lenses; + }); + } } diff --git a/Source/postgres/showPostgresQuery.ts b/Source/postgres/showPostgresQuery.ts index 4d1b277b4..7d6e2aa1d 100644 --- a/Source/postgres/showPostgresQuery.ts +++ b/Source/postgres/showPostgresQuery.ts @@ -3,18 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { postgresBaseFileName, postgresFileExtension } from "../constants"; -import * as vscodeUtil from "../utils/vscodeUtils"; +import { postgresBaseFileName, postgresFileExtension } from '../constants'; +import * as vscodeUtil from '../utils/vscodeUtils'; import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; -export async function showPostgresQuery( - treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem -): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile( - treeItem.definition, - fileName, - postgresFileExtension - ); +export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { + const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; + await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); } diff --git a/Source/postgres/tree/ClientConfigFactory.ts b/Source/postgres/tree/ClientConfigFactory.ts index 67a00710c..271f5b92f 100644 --- a/Source/postgres/tree/ClientConfigFactory.ts +++ b/Source/postgres/tree/ClientConfigFactory.ts @@ -3,123 +3,84 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - parseError, -} from "@microsoft/vscode-azext-utils"; +import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { - getAzureAdUserSession, - getTokenFunction, -} from "../../azureAccountUtils"; +import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; import { localize } from "../../utils/localize"; -import { - PostgresClientConfigType, - getClientConfigs, - testClientConfig, -} from "../getClientConfig"; -import { - firewallNotConfiguredErrorType, - invalidCredentialsErrorType, - timeoutErrorType, -} from "../postgresConstants"; +import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; +import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -export const postgresResourceType = - "https://ossrdbms-aad.database.windows.net/"; +export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; /** * Creates an object that can be used to execute a postgres query with connection test and telemetry. */ export class PostgresClientConfigFactory { - public static async getClientConfigFromNode( - treeItem: PostgresServerTreeItem, - databaseName: string - ): Promise<{ - type: "azureAd" | "password" | "connectionString"; - clientConfig: ClientConfig; - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); + public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ + type: "azureAd" | "password" | "connectionString", + clientConfig: ClientConfig + }> { + const parsedConnectionString = await treeItem.getFullConnectionString(); + const azureUserSession = await getAzureAdUserSession(); - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction( - subscription.credentials, - postgresResourceType - ); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); + let hasSubscription: boolean = false; + let tokenFunction: (() => Promise) | undefined = undefined; + try { + const subscription = treeItem.subscription; + hasSubscription = true; + tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); + } catch (error) { + hasSubscription = false; + } + const clientConfigs = await getClientConfigs( + parsedConnectionString, + treeItem.serverType, + hasSubscription, + databaseName, + azureUserSession?.userId, + tokenFunction + ); - const clientConfigTypeOrder: PostgresClientConfigType[] = [ - "azureAd", - "password", - "connectionString", - ]; + const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = - clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } + for (const clientConfigType of clientConfigTypeOrder) { + const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; + if (!clientConfig) { + continue; + } - try { - await callWithTelemetryAndErrorHandling( - "postgreSQL.testClientConfig", - async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = - clientConfigType; - await testClientConfig(clientConfig); - } - ); - return { - type: clientConfigType, - clientConfig, - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if ( - parsedError.errorType === firewallNotConfiguredErrorType || - parsedError.errorType === timeoutErrorType - ) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize( - "mustConfigureFirewall", - "Must configure firewall from Azure Portal to grant access." - ), - code: firewallNotConfiguredErrorType, - }; - } else { - throw error; - } - } - } + try { + await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { + context.errorHandling.rethrow = true; + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.clientConfigType = clientConfigType; + await testClientConfig(clientConfig); + }); + return { + type: clientConfigType, + clientConfig + }; + } catch (error) { + const parsedError = parseError(error); + if (parsedError.errorType === invalidCredentialsErrorType) { + // If the client config failed with invalid credential error, skip and try the next available one. + } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { + // The time out error are common when the firewall rules doesn't grant access from the current IP address. + // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. + throw { + message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), + code: firewallNotConfiguredErrorType + }; + } else { + throw error; + } + } + } - throw { - message: localize( - "mustEnterCredentials", - "Must enter credentials to connect to server." - ), - code: invalidCredentialsErrorType, - }; - } + throw { + message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), + code: invalidCredentialsErrorType + }; + } } diff --git a/Source/postgres/tree/PostgresColumnTreeItem.ts b/Source/postgres/tree/PostgresColumnTreeItem.ts index aedfa46f2..d284c8122 100644 --- a/Source/postgres/tree/PostgresColumnTreeItem.ts +++ b/Source/postgres/tree/PostgresColumnTreeItem.ts @@ -3,30 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; +import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { PostgresTableTreeItem } from './PostgresTableTreeItem'; export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; + public static contextValue: string = "postgresColumn"; + public readonly contextValue: string = PostgresColumnTreeItem.contextValue; + public readonly columnName: string; + public readonly parent: PostgresTableTreeItem; - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } + constructor(parent: PostgresTableTreeItem, columnName: string) { + super(parent); + this.columnName = columnName; + } - public get id(): string { - return this.columnName; - } + public get id(): string { + return this.columnName; + } - public get label(): string { - return this.columnName; - } + public get label(): string { + return this.columnName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('split-horizontal'); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("split-horizontal"); - } } diff --git a/Source/postgres/tree/PostgresDatabaseTreeItem.ts b/Source/postgres/tree/PostgresDatabaseTreeItem.ts index e9463d0bc..05f7a4412 100644 --- a/Source/postgres/tree/PostgresDatabaseTreeItem.ts +++ b/Source/postgres/tree/PostgresDatabaseTreeItem.ts @@ -4,178 +4,112 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line import/no-internal-modules -import { - AzExtParentTreeItem, - AzExtTreeItem, - createContextValue, - GenericTreeItem, - IActionContext, - IParsedError, - parseError, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { - firewallNotConfiguredErrorType, - invalidCredentialsErrorType, -} from "../postgresConstants"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresClientConfigFactory } from "./ClientConfigFactory"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; -import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; -import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; +import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { ThemeIcon } from 'vscode'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; +import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; +import { PostgresClientConfigFactory } from './ClientConfigFactory'; +import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; +import { PostgresServerTreeItem } from './PostgresServerTreeItem'; +import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; +import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; + public static contextValue: string = "postgresDatabase"; + public contextValue: string = PostgresDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Resource Type"; + public readonly databaseName: string; + public readonly parent: PostgresServerTreeItem; + public autoSelectInTreeItemPicker: boolean = true; + public isShowingPasswordWarning: boolean; - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } + constructor(parent: PostgresServerTreeItem, databaseName: string) { + super(parent); + this.databaseName = databaseName; + this.isShowingPasswordWarning = false; + } - public get label(): string { - return this.databaseName; - } + public get label(): string { + return this.databaseName; + } - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId - ? localize("connected", "Connected") - : ""; - } + public get description(): string { + return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; + } - public get id(): string { - return this.databaseName; - } + public get id(): string { + return this.databaseName; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("database"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('database'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl( - _clearCache: boolean, - context: IActionContext - ): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: "postgresFirewall", - label: localize( - "configureFirewall", - 'Configure firewall to connect to "{0}"...', - this.parent.label - ), - commandId: "postgreSQL.configureFirewall", - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } + public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { + const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: 'postgresFirewall', + label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), + commandId: 'postgreSQL.configureFirewall' + }); + firewallTreeItem.commandArgs = [this.parent]; + return [firewallTreeItem]; + } - try { - const { type, clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this.parent, - this.databaseName - ); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig), - ]; + try { + const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); + if (type === "password") { + void this.showPasswordWarning(context); + } + const children: AzExtTreeItem[] = [ + new PostgresFunctionsTreeItem(this, clientConfig), + new PostgresTablesTreeItem(this, clientConfig) + ]; - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push( - new PostgresStoredProceduresTreeItem(this, clientConfig) - ); - } + if (await this.parent.supportsStoredProcedures(clientConfig)) { + children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); + } - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); + return children; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if ( - this.parent.azureName && - parsedError.errorType === invalidCredentialsErrorType - ) { - void context.ui.showWarningMessage( - localize( - "couldNotConnect", - 'Could not connect to "{0}": {1}', - this.parent.label, - parsedError.message - ), - { stepName: "loadPostgresDatabases" } - ); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem( - this, - { - contextValue: "postgresCredentials", - label: localize( - "enterCredentials", - 'Enter server credentials to connect to "{0}"...', - this.parent.label - ), - commandId: "postgreSQL.enterCredentials", - } - ); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if ( - this.parent.azureName && - parsedError.errorType === firewallNotConfiguredErrorType - ) { - void context.ui.showWarningMessage( - localize( - "couldNotConnect", - 'Could not connect to "{0}": {1}', - this.parent.label, - parsedError.message - ), - { stepName: "loadPostgresDatabases" } - ); - return []; - } else { - throw error; - } - } - } + if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { + void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); + const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: 'postgresCredentials', + label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), + commandId: 'postgreSQL.enterCredentials' + }); + credentialsTreeItem.commandArgs = [this.parent]; + return [credentialsTreeItem]; + } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { + void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); + return []; + } else { + throw error; + } + } + } - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this.parent, - this.databaseName - ); - await runPostgresQuery( - clientConfig, - `Drop Database ${wrapArgInQuotes(this.databaseName)};` - ); - } + public async deleteTreeItemImpl(): Promise { + const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); + await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); + } - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([ - PostgresDatabaseTreeItem.contextValue, - "usesPassword", - ]); - await this.refresh(context); - } + private async showPasswordWarning(context: IActionContext): Promise { + if (this.isShowingPasswordWarning) { + return; + } + this.isShowingPasswordWarning = true; + this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); + await this.refresh(context); + } } diff --git a/Source/postgres/tree/PostgresFunctionTreeItem.ts b/Source/postgres/tree/PostgresFunctionTreeItem.ts index d7bc46a16..0a26bf3f9 100644 --- a/Source/postgres/tree/PostgresFunctionTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionTreeItem.ts @@ -10,49 +10,39 @@ import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresFunction"; - public readonly contextValue: string = - PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = 'postgresFunction'; + public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; + public readonly parent: PostgresFunctionsTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor( - parent: PostgresFunctionsTreeItem, - row: IPostgresProceduresQueryRow, - isDuplicate: boolean - ) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = "postgreSQL.openFunction"; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = 'postgreSQL.openFunction'; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("symbol-function"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('symbol-function'); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery( - this.parent.clientConfig, - `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${ - this.args - });` - ); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); + } } diff --git a/Source/postgres/tree/PostgresFunctionsTreeItem.ts b/Source/postgres/tree/PostgresFunctionsTreeItem.ts index 8f373ab95..7d3904e83 100644 --- a/Source/postgres/tree/PostgresFunctionsTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionsTreeItem.ts @@ -4,51 +4,43 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from "vscode"; -import { - getPostgresProcedureQueryRows, - IPostgresProceduresQueryRow, -} from "../getPostgresProcedureQueryRows"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { ClientConfig } from 'pg'; +import { ThemeIcon } from 'vscode'; +import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; +import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; +import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresFunctions"; - public readonly contextValue: string = - PostgresFunctionsTreeItem.contextValue; - public readonly label: string = "Functions"; - public readonly childTypeLabel: string = "Function"; - public suppressMaskLabel = true; + public static contextValue: string = 'postgresFunctions'; + public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; + public readonly label: string = 'Functions'; + public readonly childTypeLabel: string = 'Function'; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("symbol-function"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('symbol-function'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = - await getPostgresProcedureQueryRows(this); - return rows.map( - (row) => - new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - ) - ); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); + return rows.map(row => new PostgresFunctionTreeItem( + this, + row, + this.isDuplicateResource(row.name) + )); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresFunctionTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts index 40e4d07c5..b93cc9450 100644 --- a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts +++ b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts @@ -9,19 +9,19 @@ import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; // Base class for Postgres tree items whose children are individual resources export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas + public parent: PostgresDatabaseTreeItem; + public clientConfig: ClientConfig; + public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } + public addResourcesAndSchemasEntry(name: string, schema: string): void { + if (this.resourcesAndSchemas[name]) { + this.resourcesAndSchemas[name].push(schema); + } else { + this.resourcesAndSchemas[name] = [schema]; + } + } - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } + public isDuplicateResource(name: string): boolean { + return this.resourcesAndSchemas[name].length > 1; + } } diff --git a/Source/postgres/tree/PostgresServerTreeItem.ts b/Source/postgres/tree/PostgresServerTreeItem.ts index 1ffc11403..20e7dbe76 100644 --- a/Source/postgres/tree/PostgresServerTreeItem.ts +++ b/Source/postgres/tree/PostgresServerTreeItem.ts @@ -3,383 +3,250 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; -import { - getResourceGroupFromId, - parseAzureResourceId, - uiUtils, -} from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - IActionContext, - ICreateChildImplContext, -} from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { SemVer, coerce, gte } from "semver"; -import * as vscode from "vscode"; -import { - getThemeAgnosticIconPath, - postgresDefaultDatabase, -} from "../../constants"; -import { ext } from "../../extensionVariables"; -import { isIpInRanges } from "../../utils/getIp"; -import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { - AbstractPostgresClient, - createAbstractPostgresClient, -} from "../abstract/AbstractPostgresClient"; -import { PostgresAbstractServer, PostgresServerType } from "../abstract/models"; -import { getPublicIp } from "../commands/configurePostgresFirewall"; -import { ParsedPostgresConnectionString } from "../postgresConnectionStrings"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresClientConfigFactory } from "./ClientConfigFactory"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; -import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; -import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; +import * as SingleModels from '@azure/arm-postgresql'; +import * as FlexibleModels from '@azure/arm-postgresql-flexible'; +import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; +import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; +import { ClientConfig } from 'pg'; +import { SemVer, coerce, gte } from 'semver'; +import * as vscode from 'vscode'; +import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { isIpInRanges } from '../../utils/getIp'; +import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; +import { localize } from '../../utils/localize'; +import { nonNullProp } from '../../utils/nonNull'; +import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; +import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; +import { getPublicIp } from '../commands/configurePostgresFirewall'; +import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; +import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; +import { PostgresClientConfigFactory } from './ClientConfigFactory'; +import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; +import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; +import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; +import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; +import { PostgresTableTreeItem } from './PostgresTableTreeItem'; +import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = - "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor( - parent: AzExtParentTreeItem, - connectionString: ParsedPostgresConnectionString, - server?: PostgresAbstractServer - ) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId) - .provider.toLowerCase() - .includes("flexible") - ? PostgresServerType.Flexible - : PostgresServerType.Single; - } - this.valuesToMask.push( - connectionString.accountId, - connectionString.connectionString, - connectionString.fullId, - connectionString.hostName, - connectionString.port - ); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): - | string - | vscode.Uri - | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath("PostgresServer.svg"); - } - - public get label(): string { - return this.azureName - ? this.azureName - : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean, - context: IActionContext - ): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = - await createAbstractPostgresClient(this.serverType, [ - context, - this.subscription, - ]); - const listOfDatabases: ( - | SingleModels.Database - | FlexibleModels.Database - )[] = await uiUtils.listAllIterator( - client.databases.listByServer( - nonNullProp(this, "resourceGroup"), - nonNullProp(this, "azureName") - ) - ); - dbNames = listOfDatabases.map((db) => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this, - postgresDefaultDatabase - ); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map((db) => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - "invalidPostgresServer", - (dbName) => - dbName && !["azure_maintenance", "azure_sys"].includes(dbName) - ? new PostgresDatabaseTreeItem(this, dbName) - : undefined, - (dbName) => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error( - localize( - "noPermissionToCreateDatabase", - `This attached account does not have permissions to create a database.` - ) - ); - } - const getChildrenTask: Promise = - this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: "createPostgresDatabase", - validateInput: (name: string) => - validateDatabaseName(name, getChildrenTask), - }); - const { clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this, - databaseName - ); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery( - clientConfig, - `Create Database ${wrapArgInQuotes(databaseName)};` - ); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [ - context, - this.subscription, - ]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: deletingMessage, - }, - async () => { - await client.servers.beginDeleteAndWait( - nonNullProp(this, "resourceGroup"), - nonNullProp(this, "azureName") - ); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize( - "deleteServerMsg", - 'Successfully deleted server "{0}".', - this.label - ); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - } - ); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures( - clientConfig: ClientConfig - ): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery( - clientConfig, - `SHOW server_version;` - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, "11.0.0"); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = - ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue - ? JSON.parse(storedValue) - : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { - return server.id !== this.id; - }); - - await ext.context.globalState.update( - serviceName, - JSON.stringify(servers) - ); - await ext.secretStorage.delete( - getSecretStorageKey(serviceName, this.id) - ); - } - - public async getFullConnectionString(): Promise { - if ( - this.azureId && - !( - this.partialConnectionString.username && - this.partialConnectionString.password - ) - ) { - const storedValue: string | undefined = ext.context.globalState.get( - PostgresServerTreeItem.serviceName - ); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = - (await ext.secretStorage.get( - getSecretStorageKey( - PostgresServerTreeItem.serviceName, - this.id - ) - )) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp( - this, - "serverType" - ); - const client: AbstractPostgresClient = - await createAbstractPostgresClient(serverType, [ - context, - this.subscription, - ]); - const results: SingleModels.FirewallRule[] = - await uiUtils.listAllIterator( - client.firewallRules.listByServer( - nonNullProp(this, "resourceGroup"), - nonNullProp(this, "azureName") - ) - ); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } + public static contextValue: string = "postgresServer"; + public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; + public readonly contextValue: string = PostgresServerTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly serverType: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { + super(parent); + this.partialConnectionString = connectionString; + if (server) { + this.azureId = server?.id; + this.serverVersion = server?.version; + this.resourceGroup = getResourceGroupFromId(this.fullId); + this.azureName = server?.name; + this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; + } + this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); + if (connectionString.databaseName) { + this.valuesToMask.push(connectionString.databaseName); + } + } + + public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath('PostgresServer.svg'); + } + + public get label(): string { + return this.azureName ? this.azureName : this.partialConnectionString.fullId; + } + + public get id(): string { + if (this.azureId) { + return this.azureId; + } + return this.partialConnectionString.fullId; + } + + public get description(): string | undefined { + switch (this.serverType) { + case PostgresServerType.Flexible: + return "PostgreSQL Flexible"; + case PostgresServerType.Single: + return "PostgreSQL Single"; + default: + return "PostgreSQL"; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { + context.telemetry.properties.serverType = this.serverType; + let dbNames: (string | undefined)[]; + if (this.azureName) { + const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); + const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); + dbNames = listOfDatabases.map(db => db.name); + } else if (this.partialConnectionString.databaseName) { + dbNames = [this.partialConnectionString.databaseName]; + } else { + const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); + const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; + const queryResult = await runPostgresQuery(clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + dbNames = queryResult.rows.map(db => db?.datname); + } + + return this.createTreeItemsWithErrorHandling( + dbNames, + 'invalidPostgresServer', + dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, + dbName => dbName + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case PostgresDatabaseTreeItem.contextValue: + case PostgresTablesTreeItem.contextValue: + case PostgresTableTreeItem.contextValue: + case PostgresFunctionsTreeItem.contextValue: + case PostgresFunctionTreeItem.contextValue: + case PostgresStoredProceduresTreeItem.contextValue: + case PostgresStoredProcedureTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + if (this.partialConnectionString.databaseName) { + throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); + } + const getChildrenTask: Promise = this.getCachedChildren(context); + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: 'createPostgresDatabase', + validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) + }); + const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); + context.showCreatingTreeItem(databaseName); + await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); + return new PostgresDatabaseTreeItem(this, databaseName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); + const deletingMessage: string = `Deleting server "${this.label}"...`; + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { + await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); + await this.deletePostgresCredentials(); + + const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + }); + } + + public setCredentials(username: string, password: string): void { + this.partialConnectionString.username = username; + this.partialConnectionString.password = password; + } + + public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { + // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer + if (!this.serverVersion) { + const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + this.serverVersion = result.rows[0].server_version; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + const version: SemVer | null = coerce(this.serverVersion); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call + return gte(version, '11.0.0'); + } + + public async deletePostgresCredentials(): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; + + // Remove this server from the cache + servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); + + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); + } + + public async getFullConnectionString(): Promise { + + if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { + const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); + if (storedValue) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const servers: IPersistedServer[] = JSON.parse(storedValue); + for (const server of servers) { + if (server.id === this.id) { + this.partialConnectionString.username = server.username; + // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials + this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; + break; + } + } + } + } + return this.partialConnectionString; + } + + /** + * @returns true if we believe the firewall allows the current IP to connect to database server. + */ + public async isFirewallRuleSet(context: IActionContext): Promise { + try { + const serverType: PostgresServerType = nonNullProp(this, 'serverType'); + const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); + const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); + const publicIp: string = await getPublicIp(context); + return isIpInRanges(publicIp, results); + } catch (error) { + // We cannot get the firewall rules from attached databases because we cannot get the subscription object. + // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. + return true; + } + } } -async function validateDatabaseName( - name: string, - getChildrenTask: Promise -): Promise { - if (!name) { - return localize("NameCannotBeEmpty", "Name cannot be empty."); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize("NameExists", 'Database "{0}" already exists.', name); - } - return undefined; +async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { + if (!name) { + return localize('NameCannotBeEmpty', 'Name cannot be empty.'); + } + const currDatabaseList = await getChildrenTask; + const currDatabaseNames: string[] = []; + for (const db of currDatabaseList) { + if (db instanceof PostgresDatabaseTreeItem) { + currDatabaseNames.push(db.databaseName); + } + } + if (currDatabaseNames.includes(name)) { + return localize('NameExists', 'Database "{0}" already exists.', name); + } + return undefined; } diff --git a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts index 1c903d9e2..503d0ae74 100644 --- a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts @@ -10,47 +10,39 @@ import { runPostgresQuery } from "../runPostgresQuery"; import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresStoredProcedure"; - public readonly contextValue: string = - PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = 'postgresStoredProcedure'; + public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; + public readonly parent: PostgresStoredProceduresTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor( - parent: PostgresStoredProceduresTreeItem, - row: IPostgresProceduresQueryRow, - isDuplicate: boolean - ) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = "postgreSQL.openStoredProcedure"; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = 'postgreSQL.openStoredProcedure'; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("server-process"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('server-process'); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery( - this.parent.clientConfig, - `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});` - ); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); + } } diff --git a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts index 9525856f6..1c516e00f 100644 --- a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts @@ -4,53 +4,43 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from "vscode"; -import { - getPostgresProcedureQueryRows, - IPostgresProceduresQueryRow, -} from "../getPostgresProcedureQueryRows"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; -import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; +import { ClientConfig } from 'pg'; +import { ThemeIcon } from 'vscode'; +import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; +import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; +import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresStoredProcedures"; - public readonly contextValue: string = - PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = "Stored Procedures"; - public readonly childTypeLabel: string = "Stored Procedure"; - public suppressMaskLabel = true; + public static contextValue: string = 'postgresStoredProcedures'; + public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; + public readonly label: string = 'Stored Procedures'; + public readonly childTypeLabel: string = 'Stored Procedure'; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("server-process"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('server-process'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise< - PostgresStoredProcedureTreeItem[] - > { - const rows: IPostgresProceduresQueryRow[] = - await getPostgresProcedureQueryRows(this); - return rows.map( - (row) => - new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - ) - ); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); + return rows.map(row => new PostgresStoredProcedureTreeItem( + this, + row, + this.isDuplicateResource(row.name) + )); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresStoredProcedureTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresTableTreeItem.ts b/Source/postgres/tree/PostgresTableTreeItem.ts index fb844038b..ef5d87c2c 100644 --- a/Source/postgres/tree/PostgresTableTreeItem.ts +++ b/Source/postgres/tree/PostgresTableTreeItem.ts @@ -3,68 +3,54 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtParentTreeItem, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { IPostgresTable } from "../getTables"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresColumnTreeItem } from "./PostgresColumnTreeItem"; -import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; +import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { IPostgresTable } from '../getTables'; +import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; +import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; +import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; + public static contextValue: string = "postgresTable"; + public readonly contextValue: string = PostgresTableTreeItem.contextValue; + public readonly table: IPostgresTable; + public readonly parent: PostgresTablesTreeItem; - private _isDuplicate: boolean; + private _isDuplicate: boolean; - constructor( - parent: PostgresTablesTreeItem, - table: IPostgresTable, - isDuplicate: boolean - ) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } + constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { + super(parent); + this.table = table; + this._isDuplicate = isDuplicate; + } - public get id(): string { - return String(this.table.oid); - } + public get id(): string { + return String(this.table.oid); + } - public get label(): string { - return this.table.name; - } + public get label(): string { + return this.table.name; + } - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } + public get description(): string | undefined { + return this._isDuplicate ? this.table.schemaName : undefined; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("window"); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('window'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - return this.table.columnNames.map( - (columnName) => new PostgresColumnTreeItem(this, columnName) - ); - } + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + + return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); + } + + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery( - this.parent.clientConfig, - `Drop Table ${this.table.schemaName}.${wrapArgInQuotes( - this.table.name - )};` - ); - } } diff --git a/Source/postgres/tree/PostgresTablesTreeItem.ts b/Source/postgres/tree/PostgresTablesTreeItem.ts index 4c15ef812..c18c065db 100644 --- a/Source/postgres/tree/PostgresTablesTreeItem.ts +++ b/Source/postgres/tree/PostgresTablesTreeItem.ts @@ -5,54 +5,47 @@ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { ThemeIcon } from "vscode"; +import { ThemeIcon } from 'vscode'; import { getTables, IPostgresTable } from "../getTables"; import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = "Tables"; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("window"); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry( - table.name.trim(), - table.schemaName - ); - } - return tables.map( - (table) => - new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - ) - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } + public static contextValue: string = "postgresTables"; + public readonly contextValue: string = PostgresTablesTreeItem.contextValue; + public readonly childTypeLabel: string = "Table"; + public readonly label: string = 'Tables'; + public suppressMaskLabel = true; + + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } + + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('window'); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + + const tables: IPostgresTable[] = await getTables(this.clientConfig); + this.resourcesAndSchemas = {}; + for (const table of tables) { + this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); + } + return tables.map(table => new PostgresTableTreeItem( + this, + table, + this.isDuplicateResource(table.name.trim()) + )); + } + + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresTableTreeItem.contextValue; + } } diff --git a/Source/resolver/AppResolver.ts b/Source/resolver/AppResolver.ts index 7d20a4832..0f75cdf29 100644 --- a/Source/resolver/AppResolver.ts +++ b/Source/resolver/AppResolver.ts @@ -4,19 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, - ISubscriptionContext, - nonNullProp, - nonNullValue, -} from "@microsoft/vscode-azext-utils"; -import { - AppResource, - AppResourceResolver, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; +import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; import { tryGetExperience } from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; import { ext } from "../extensionVariables"; @@ -24,111 +13,59 @@ import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresAbstractServer } from "../postgres/abstract/models"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { - createCosmosDBClient, - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../utils/azureClients"; +import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; const resourceTypes = [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers", + 'microsoft.documentdb/databaseaccounts', + 'microsoft.dbforpostgresql/servers', + 'microsoft.dbforpostgresql/flexibleservers' ]; export class DatabaseResolver implements AppResourceResolver { - public async resolveResource( - subContext: ISubscriptionContext, - resource: AppResource - ): Promise { - return await callWithTelemetryAndErrorHandling( - "resolveResource", - async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - `/subscriptions/${subContext.subscriptionId}`, - context - ); - try { - const resourceGroupName = getResourceGroupFromId( - nonNullProp(resource, "id") - ); - const name = nonNullProp(resource, "name"); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; + public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { + return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { + const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); + try { + const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); + const name = nonNullProp(resource, 'name'); + let postgresServer: PostgresAbstractServer; + let dbChild: AzExtTreeItem; - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ - ...context, - ...subContext, - }); - const databaseAccount = - await client.databaseAccounts.get( - resourceGroupName, - name - ); - dbChild = - await SubscriptionTreeItem.initCosmosDBChild( - client, - databaseAccount, - nonNullValue(subNode) - ); - const experience = - tryGetExperience(databaseAccount); + switch (resource.type.toLowerCase()) { + case resourceTypes[0]: + const client = await createCosmosDBClient({ ...context, ...subContext }); + const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); + dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); + const experience = tryGetExperience(databaseAccount); - return experience?.api === "MongoDB" - ? new ResolvedMongoAccountResource( - dbChild as MongoAccountTreeItem, - resource - ) - : new ResolvedDocDBAccountResource( - dbChild as DocDBAccountTreeItem, - resource - ); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = - resource.type.toLowerCase() === resourceTypes[1] - ? await createPostgreSQLClient({ - ...context, - ...subContext, - }) - : await createPostgreSQLFlexibleClient({ - ...context, - ...subContext, - }); + return experience?.api === 'MongoDB' ? + new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : + new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); + case resourceTypes[1]: + case resourceTypes[2]: + const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? + await createPostgreSQLClient({ ...context, ...subContext }) : + await createPostgreSQLFlexibleClient({ ...context, ...subContext }); - postgresServer = await postgresClient.servers.get( - resourceGroupName, - name - ); - dbChild = - await SubscriptionTreeItem.initPostgresChild( - postgresServer, - nonNullValue(subNode) - ); + postgresServer = await postgresClient.servers.get(resourceGroupName, name); + dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); - return new ResolvedPostgresServerResource( - dbChild as PostgresServerTreeItem, - resource - ); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - } - ); - } + return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); + default: + return null; + } + } catch (e) { + console.error({ ...context, ...subContext }); + throw e; + } + }); + } - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } + public matchesResource(resource: AppResource): boolean { + return resourceTypes.includes(resource.type.toLowerCase()); + } } diff --git a/Source/resolver/DatabaseWorkspaceProvider.ts b/Source/resolver/DatabaseWorkspaceProvider.ts index d1f462a36..14e50d643 100644 --- a/Source/resolver/DatabaseWorkspaceProvider.ts +++ b/Source/resolver/DatabaseWorkspaceProvider.ts @@ -3,37 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtParentTreeItem, - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; import { Disposable } from "vscode"; import { ext } from "../extensionVariables"; import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; + export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise< - AzExtTreeItem[] | null | undefined - > { - return await callWithTelemetryAndErrorHandling( - "AzureAccountTreeItemWithProjects.provideResources", - async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - } - ); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } + + public disposables: Disposable[] = []; + + constructor(parent: AzExtParentTreeItem) { + ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); + } + + public async provideResources(): Promise { + + return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { + return [ext.attachedAccountsNode]; + }); + } + private _projectDisposables: Disposable[] = []; + + public dispose(): void { + Disposable.from(...this._projectDisposables).dispose(); + } } + diff --git a/Source/resolver/ResolvedDatabaseAccountResource.ts b/Source/resolver/ResolvedDatabaseAccountResource.ts index 41eda32be..0222dded7 100644 --- a/Source/resolver/ResolvedDatabaseAccountResource.ts +++ b/Source/resolver/ResolvedDatabaseAccountResource.ts @@ -3,78 +3,55 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -export class ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?( - clearCache: boolean, - context: IActionContext - ): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?( - expectedContextValues: (string | RegExp)[], - context: IActionContext - ): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor( - ti: - | DocDBAccountTreeItemBase - | MongoAccountTreeItem - | PostgresServerTreeItem, - resource: AppResource - ) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = - ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue); - this.maskedValuestoAdd.push(...ti.valuesToMask); - } +export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + public id: string; + public contextValuesToAdd: string[] = []; + public description: string | undefined; + + // private _databaseTreeItem: AzExtParentTreeItem; + iconPath: TreeItemIconPath | undefined; + label: string; + + readonly childTypeLabel: string; + + loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; + createChildImpl?(context: ICreateChildImplContext): Promise; + hasMoreChildrenImpl?(): boolean; + compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; + + pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; + deleteTreeItemImpl?(context: IActionContext): Promise; + refreshImpl?(context: IActionContext): Promise; + isAncestorOfImpl?(contextValue: string): boolean; + + connectionString: string; + maskedValuestoAdd: string[] = []; + + public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { + this.id = ti.id ?? resource.id; + // PostgresServerTreeItem require on a property on the server so wait to do this + this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; + this.iconPath = ti.iconPath; + this.label = ti.label; + this.childTypeLabel = ti.childTypeLabel; + + this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; + this.createChildImpl = ti.createChildImpl; + this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; + this.compareChildrenImpl = ti.compareChildrenImpl; + + this.pickTreeItemImpl = ti.pickTreeItemImpl; + this.deleteTreeItemImpl = ti.deleteTreeItemImpl; + this.refreshImpl = ti.refreshImpl; + this.isAncestorOfImpl = ti.isAncestorOfImpl; + + this.contextValuesToAdd.push(ti.contextValue) + this.maskedValuestoAdd.push(...ti.valuesToMask); + } } diff --git a/Source/resolver/ResolvedDocDBAccountResource.ts b/Source/resolver/ResolvedDocDBAccountResource.ts index 02f17f6e3..cf1bfc4bc 100644 --- a/Source/resolver/ResolvedDocDBAccountResource.ts +++ b/Source/resolver/ResolvedDocDBAccountResource.ts @@ -1,45 +1,32 @@ + + /*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { - CosmosClient, - DatabaseDefinition, - FeedOptions, - QueryIterator, - Resource, -} from "@azure/cosmos"; +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ + +import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedDocDBAccountResource - extends ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: ( - client: CosmosClient, - feedOptions: FeedOptions - ) => QueryIterator; - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless; - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } +export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + public root: IDocDBTreeRoot; + + initChild: (resource: Resource) => AzExtTreeItem; + isServerless?: boolean; + getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator + + public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { + super(ti, resource); + + this.connectionString = ti.connectionString; + this.root = ti.root; + + this.isServerless = ti.isServerless + this.getIterator = ti.getIterator; + this.initChild = ti.initChild; + } } diff --git a/Source/resolver/ResolvedMongoAccountResource.ts b/Source/resolver/ResolvedMongoAccountResource.ts index 80636b5e5..4f45486ef 100644 --- a/Source/resolver/ResolvedMongoAccountResource.ts +++ b/Source/resolver/ResolvedMongoAccountResource.ts @@ -3,24 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedMongoAccountResource - extends ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - root: IMongoTreeRoot; +export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + root: IMongoTreeRoot; - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); + public constructor(ti: MongoAccountTreeItem, resource: AppResource) { + super(ti, resource); - this.connectionString = ti.connectionString; - this.root = ti.root; - } + this.connectionString = ti.connectionString; + this.root = ti.root; + } } diff --git a/Source/resolver/ResolvedPostgresServerResource.ts b/Source/resolver/ResolvedPostgresServerResource.ts index 76007eac0..a1e35acf3 100644 --- a/Source/resolver/ResolvedPostgresServerResource.ts +++ b/Source/resolver/ResolvedPostgresServerResource.ts @@ -4,54 +4,45 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { ClientConfig } from "pg"; import { PostgresServerType } from "../postgres/abstract/models"; import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedPostgresServerResource - extends ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise; - deletePostgresCredentials: () => Promise; - getFullConnectionString: () => Promise; - validateDatabaseName: ( - name: string, - getChildrenTask: Promise - ) => Promise; - isFirewallRuleSet: (context: IActionContext) => Promise; - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } +export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + public readonly serverType?: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + setCredentials: (username: string, password: string) => void; + supportsStoredProcedures: (clientConfig: ClientConfig) => Promise + deletePostgresCredentials: () => Promise + getFullConnectionString: () => Promise + validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise + isFirewallRuleSet: (context: IActionContext) => Promise + + public constructor(ti: PostgresServerTreeItem, resource: AppResource) { + super(ti, resource); + this.serverType = ti.serverType; + this.description = ti.description; + this.resourceGroup = ti.resourceGroup; + this.azureName = ti.azureName; + this.partialConnectionString = ti.partialConnectionString; + + this.azureId = ti.azureId; + this.serverVersion = ti.serverVersion; + + this.setCredentials = ti.setCredentials; + this.supportsStoredProcedures = ti.supportsStoredProcedures; + this.deletePostgresCredentials = ti.deletePostgresCredentials; + this.getFullConnectionString = ti.getFullConnectionString; + this.isFirewallRuleSet = ti.isFirewallRuleSet; + } } diff --git a/Source/table/tree/TableAccountTreeItem.ts b/Source/table/tree/TableAccountTreeItem.ts index fb2616da9..0d3b86e38 100644 --- a/Source/table/tree/TableAccountTreeItem.ts +++ b/Source/table/tree/TableAccountTreeItem.ts @@ -4,40 +4,36 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBTableAccount"; + public contextValue: string = TableAccountTreeItem.contextValue; - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public initChild(): AzExtTreeItem { - throw new Error("Table Accounts are not supported yet."); - } + public initChild(): AzExtTreeItem { + throw new Error('Table Accounts are not supported yet.'); + } - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: "tableNotSupported", - label: "Table Accounts are not supported yet.", - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: 'tableNotSupported', + label: 'Table Accounts are not supported yet.' + }); + tableNotFoundTreeItem.suppressMaskLabel = true; + return [tableNotFoundTreeItem]; + } - public async deleteTreeItemImpl( - context: IDeleteWizardContext - ): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { + await deleteCosmosDBAccount(context, this); + } - public isAncestorOfImpl(): boolean { - return false; - } + public isAncestorOfImpl(): boolean { + return false; + } } diff --git a/Source/tree/AttachedAccountsTreeItem.ts b/Source/tree/AttachedAccountsTreeItem.ts index 47aa8bdc3..d854e506f 100644 --- a/Source/tree/AttachedAccountsTreeItem.ts +++ b/Source/tree/AttachedAccountsTreeItem.ts @@ -3,605 +3,418 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - appendExtensionUserAgent, - AzExtParentTreeItem, - AzExtTreeItem, - GenericTreeItem, - IActionContext, - ISubscriptionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import * as vscode from "vscode"; -import { - API, - getExperienceFromApi, - getExperienceQuickPick, - getExperienceQuickPicks, -} from "../AzureDBExperiences"; -import { removeTreeItemFromCache } from "../commands/api/apiCache"; -import { emulatorPassword, isWindows } from "../constants"; -import { parseDocDBConnectionString } from "../docdb/docDBConnectionStrings"; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { ext } from "../extensionVariables"; -import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { connectToMongoClient } from "../mongo/connectToMongoClient"; -import { parseMongoConnectionString } from "../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { parsePostgresConnectionString } from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { getSecretStorageKey } from "../utils/getSecretStorageKey"; -import { localize } from "../utils/localize"; -import { nonNullProp, nonNullValue } from "../utils/nonNull"; -import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; +import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { MongoClient } from 'mongodb'; +import * as vscode from 'vscode'; +import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; +import { removeTreeItemFromCache } from '../commands/api/apiCache'; +import { emulatorPassword, isWindows } from '../constants'; +import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; +import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; +import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; +import { ext } from '../extensionVariables'; +import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; +import { connectToMongoClient } from '../mongo/connectToMongoClient'; +import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; +import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; +import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; +import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; +import { getSecretStorageKey } from '../utils/getSecretStorageKey'; +import { localize } from '../utils/localize'; +import { nonNullProp, nonNullValue } from '../utils/nonNull'; +import { SubscriptionTreeItem } from './SubscriptionTreeItem'; interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; + id: string; + // defaultExperience is not the same as API but we can't change the name due to backwards compatibility + defaultExperience: API; + isEmulator: boolean | undefined; } -export const AttachedAccountSuffix: string = "Attached"; -export const MONGO_CONNECTION_EXPECTED: string = - 'Connection string must start with "mongodb://" or "mongodb+srv://"'; +export const AttachedAccountSuffix: string = 'Attached'; +export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; -const localMongoConnectionString: string = "mongodb://127.0.0.1:27017"; +const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = - "cosmosDBAttachedAccounts" + - (isWindows ? "WithEmulator" : "WithoutEmulator"); - public readonly contextValue: string = - AttachedAccountsTreeItem.contextValue; - public readonly label: string = "Attached Database Accounts"; - public childTypeLabel: string = "Account"; - public suppressMaskLabel = true; - - private readonly _serviceName: string = - "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = "cosmosDBAttachedAccounts"; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("plug"); - } - - public static validateMongoConnectionString( - value: string - ): string | undefined { - value = value ? value.trim() : ""; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString( - value: string - ): string | undefined { - value = value ? value.trim() : ""; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize( - "invalidPostgresConnectionString", - 'Connection string must start with "postgres://"' - ); - } - - private static validateDocDBConnectionString( - value: string - ): string | undefined { - value = value ? value.trim() : ""; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = - await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: "cosmosDBAttachDatabaseAccount", - label: "Attach Database Account...", - commandId: "cosmosDB.attachDatabaseAccount", - includeInTreeItemPicker: true, - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: "cosmosDBAttachEmulator", - label: "Attach Emulator...", - commandId: "cosmosDB.attachEmulator", - includeInTreeItemPicker: true, - }); - return isWindows - ? [attachDatabaseAccount, attachEmulator] - : [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick( - getExperienceQuickPicks(true), - { - placeHolder: "Select a Database type...", - stepName: "attachNewAccount", - } - ); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = "mongodb://host:port"; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = - AttachedAccountsTreeItem.validateMongoConnectionString; - } else if ( - defaultExperience.api === API.PostgresSingle || - defaultExperience.api === API.PostgresFlexible - ) { - placeholder = localize( - "attachedPostgresPlaceholder", - '"postgres://username:password@host" or "postgres://username:password@host/database"' - ); - validateInput = - AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = "AccountEndpoint=...;AccountKey=..."; - validateInput = - AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = ( - await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: "Enter the connection string for your database account", - stepName: "attachNewAccountConnectionString", - validateInput: validateInput, - value: defaultValue, - }) - ).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem( - connectionString, - defaultExperience.api - ); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString( - context: IActionContext, - connectionString: string, - api: API.MongoDB | API.Core | API.PostgresSingle - ): Promise< - MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem - > { - const treeItem = < - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem - >await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core), - ], - { - placeHolder: "Select a Database Account API...", - stepName: "attachEmulator", - } - ); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace - .getConfiguration() - .get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace - .getConfiguration() - .get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent( - emulatorPassword - )}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem( - connectionString, - defaultExperience.api, - label - ); - if ( - treeItem instanceof DocDBAccountTreeItem || - treeItem instanceof GraphAccountTreeItem || - treeItem instanceof TableAccountTreeItem || - treeItem instanceof MongoAccountTreeItem - ) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = - await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex( - (account) => account.fullId === node.fullId - ); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete( - getSecretStorageKey(this._serviceName, nonNullProp(node, "id")) - ); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString( - node.connectionString - ); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString( - node.connectionString - ); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error( - "Failed to load persisted Database Accounts. Reattach the accounts manually." - ); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient( - localMongoConnectionString, - appendExtensionUserAgent() - ); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount( - context: IActionContext, - treeItem: AzExtTreeItem, - connectionString: string - ): Promise { - const attachedAccounts: AzExtTreeItem[] = - await this.getAttachedAccounts(); - - if (attachedAccounts.find((s) => s.id === treeItem.id)) { - void context.ui.showWarningMessage( - `Database Account '${treeItem.id}' is already attached.`, - { stepName: "attachAccount" } - ); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store( - getSecretStorageKey( - this._serviceName, - nonNullProp(treeItem, "id") - ), - connectionString - ); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get( - this._serviceName - ); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all( - accounts.map(async (account) => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof account === "string") { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${ - getExperienceFromApi(api).shortName - })`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator - ? `${getExperienceFromApi(api).shortName} Emulator` - : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue( - await ext.secretStorage.get( - getSecretStorageKey(this._serviceName, id) - ), - "connectionString" - ); - persistedAccounts.push( - await this.createTreeItem( - connectionString, - api, - label, - id, - isEmulator - ) - ); - }) - ); - } - - return persistedAccounts; - } - - private async createTreeItem( - connectionString: string, - api: API, - label?: string, - id?: string, - isEmulator?: boolean - ): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = - await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem( - this, - id, - label, - connectionString, - isEmulator - ); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = - parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem( - this, - parsedPostgresConnString - ); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = - label || - `${parsedCS.accountId} (${ - getExperienceFromApi(api).shortName - })`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem( - this, - parsedCS.accountId, - label, - parsedCS.documentEndpoint, - parsedCS.masterKey, - isEmulator - ); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem( - this, - parsedCS.accountId, - label, - parsedCS.documentEndpoint, - undefined, - parsedCS.masterKey, - isEmulator - ); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem( - this, - parsedCS.accountId, - label, - parsedCS.documentEndpoint, - parsedCS.masterKey, - isEmulator - ); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map( - (node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if ( - node instanceof MongoAccountTreeItem || - node instanceof DocDBAccountTreeItem || - node instanceof GraphAccountTreeItem || - node instanceof TableAccountTreeItem - ) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error( - `Unexpected account node "${node.constructor.name}".` - ); - } - return { - id: nonNullProp(node, "id"), - defaultExperience: api, - isEmulator: isEmulator, - }; - } - ); - await ext.context.globalState.update( - this._serviceName, - JSON.stringify(value) - ); - } + public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); + public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; + public readonly label: string = 'Attached Database Accounts'; + public childTypeLabel: string = 'Account'; + public suppressMaskLabel = true; + + private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; + private _attachedAccounts: AzExtTreeItem[] | undefined; + + private _root: ISubscriptionContext; + private _loadPersistedAccountsTask: Promise; + + constructor(parent: AzExtParentTreeItem) { + super(parent); + this._root = new AttachedAccountRoot(); + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + this.id = 'cosmosDBAttachedAccounts'; + } + + public get root(): ISubscriptionContext { + return this._root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('plug'); + } + + public static validateMongoConnectionString(value: string): string | undefined { + value = value ? value.trim() : ''; + + if (value && value.match(/^mongodb(\+srv)?:\/\//)) { + return undefined; + } + + return MONGO_CONNECTION_EXPECTED; + } + + public static validatePostgresConnectionString(value: string): string | undefined { + value = value ? value.trim() : ''; + + if (value && value.match(/^postgres:\/\//)) { + return undefined; + } + + return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); + } + + private static validateDocDBConnectionString(value: string): string | undefined { + value = value ? value.trim() : ''; + + try { + parseDocDBConnectionString(value); + return undefined; + } catch (error) { + return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (clearCache) { + this._attachedAccounts = undefined; + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + } + + const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); + + if (attachedAccounts.length > 0) { + return attachedAccounts; + } else { + const attachDatabaseAccount = new GenericTreeItem(this, { + contextValue: 'cosmosDBAttachDatabaseAccount', + label: 'Attach Database Account...', + commandId: 'cosmosDB.attachDatabaseAccount', + includeInTreeItemPicker: true + }); + const attachEmulator = new GenericTreeItem(this, { + contextValue: 'cosmosDBAttachEmulator', + label: 'Attach Emulator...', + commandId: 'cosmosDB.attachEmulator', + includeInTreeItemPicker: true + }); + return isWindows ? [attachDatabaseAccount, attachEmulator] : + [attachDatabaseAccount]; + } + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + // We have to make sure the Attached Accounts node is not shown for commands like + // 'Open in Portal', which only work for the non-attached version + case GraphAccountTreeItem.contextValue: + case MongoAccountTreeItem.contextValue: + case DocDBAccountTreeItem.contextValue: + case TableAccountTreeItem.contextValue: + case PostgresServerTreeItem.contextValue: + case SubscriptionTreeItem.contextValue: + return false; + default: + return true; + } + } + + public async attachNewAccount(context: IActionContext): Promise { + const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); + const defaultExperience = defaultExperiencePick.data; + let placeholder: string; + let defaultValue: string | undefined; + let validateInput: (value: string) => string | undefined | null; + if (defaultExperience.api === API.MongoDB) { + placeholder = 'mongodb://host:port'; + if (await this.canConnectToLocalMongoDB()) { + defaultValue = placeholder = localMongoConnectionString; + } + validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; + } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { + placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); + validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; + } else { + placeholder = 'AccountEndpoint=...;AccountKey=...'; + validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; + } + + const connectionString = (await context.ui.showInputBox({ + placeHolder: placeholder, + prompt: 'Enter the connection string for your database account', + stepName: 'attachNewAccountConnectionString', + validateInput: validateInput, + value: defaultValue + })).trim(); + + const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); + await this.attachAccount(context, treeItem, connectionString); + } + + public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { + const treeItem = await this.createTreeItem(connectionString, api); + await this.attachAccount(context, treeItem, connectionString); + await this.refresh(context); + return treeItem; + } + + public async attachEmulator(context: IActionContext): Promise { + let connectionString: string; + const defaultExperiencePick = await context.ui.showQuickPick( + [ + getExperienceQuickPick(API.MongoDB), + getExperienceQuickPick(API.Core) + ], + { + placeHolder: "Select a Database Account API...", + stepName: 'attachEmulator' + }); + const defaultExperience = defaultExperiencePick.data; + let port: number | undefined; + if (defaultExperience.api === API.MongoDB) { + port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); + } else { + port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); + } + if (port) { + if (defaultExperience.api === API.MongoDB) { + // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions + connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; + } else { + connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; + } + const label = `${defaultExperience.shortName} Emulator`; + const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); + if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { + // CONSIDER: Why isn't this passed in to createTreeItem above? + treeItem.root.isEmulator = true; + } + await this.attachAccount(context, treeItem, connectionString); + } + } + + public async detach(node: AzExtTreeItem): Promise { + const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); + + const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); + if (index !== -1) { + attachedAccounts.splice(index, 1); + await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility + await this.persistIds(attachedAccounts); + + if (node instanceof MongoAccountTreeItem) { + const parsedCS = await parseMongoConnectionString(node.connectionString); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof DocDBAccountTreeItemBase) { + const parsedCS = parseDocDBConnectionString(node.connectionString); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof PostgresServerTreeItem) { + const parsedCS = node.partialConnectionString; + removeTreeItemFromCache(parsedCS); + } + } + } + + private async getAttachedAccounts(): Promise { + if (!this._attachedAccounts) { + try { + this._attachedAccounts = await this._loadPersistedAccountsTask; + } catch { + this._attachedAccounts = []; + throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); + } + } + + return this._attachedAccounts; + } + + private async canConnectToLocalMongoDB(): Promise { + async function timeout(): Promise { + await delay(1000); + return false; + } + async function connect(): Promise { + try { + const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); + void db.close(); + return true; + } catch { + return false; + } + } + return await Promise.race([timeout(), connect()]); + } + + private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { + const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); + + if (attachedAccounts.find(s => s.id === treeItem.id)) { + void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); + } else { + attachedAccounts.push(treeItem); + await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); + await this.persistIds(attachedAccounts); + } + } + + private async loadPersistedAccounts(): Promise { + const persistedAccounts: AzExtTreeItem[] = []; + const value: string | undefined = ext.context.globalState.get(this._serviceName); + if (value) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const accounts: (string | IPersistedAccount)[] = JSON.parse(value); + await Promise.all(accounts.map(async account => { + let id: string; + let label: string; + let api: API; + let isEmulator: boolean | undefined; + if (typeof (account) === 'string') { + // Default to Mongo if the value is a string for the sake of backwards compatibility + // (Mongo was originally the only account type that could be attached) + id = account; + api = API.MongoDB; + label = `${account} (${getExperienceFromApi(api).shortName})`; + isEmulator = false; + } else { + id = (account).id; + api = (account).defaultExperience; + isEmulator = (account).isEmulator; + label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; + } + // TODO: keytar: migration plan? + const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); + persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); + })); + } + + return persistedAccounts; + } + + private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { + let treeItem: AzExtTreeItem; + if (api === API.MongoDB) { + if (id === undefined) { + const parsedCS = await parseMongoConnectionString(connectionString); + id = parsedCS.fullId; + } + + label = label || `${id} (${getExperienceFromApi(api).shortName})`; + treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); + } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { + const parsedPostgresConnString = parsePostgresConnectionString(connectionString); + treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); + } else { + const parsedCS = parseDocDBConnectionString(connectionString); + + label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; + switch (api) { + case API.Table: + treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); + break; + case API.Graph: + treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); + break; + case API.Core: + treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); + break; + default: + throw new Error(`Unexpected defaultExperience "${api}".`); + } + } + + treeItem.contextValue += AttachedAccountSuffix; + return treeItem; + } + + private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { + const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { + let api: API; + let isEmulator: boolean | undefined; + if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { + isEmulator = node.root.isEmulator; + } + if (node instanceof MongoAccountTreeItem) { + api = API.MongoDB; + } else if (node instanceof GraphAccountTreeItem) { + api = API.Graph; + } else if (node instanceof TableAccountTreeItem) { + api = API.Table; + } else if (node instanceof DocDBAccountTreeItem) { + api = API.Core; + } else if (node instanceof PostgresServerTreeItem) { + api = API.PostgresSingle; + } else { + throw new Error(`Unexpected account node "${node.constructor.name}".`); + } + return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; + }); + await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); + } } class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error( - "Cannot retrieve Azure subscription information for an attached account." - ); + private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); - public get credentials(): never { - throw this._error; - } + public get credentials(): never { + throw this._error; + } - public get subscriptionDisplayName(): never { - throw this._error; - } + public get subscriptionDisplayName(): never { + throw this._error; + } - public get subscriptionId(): never { - throw this._error; - } + public get subscriptionId(): never { + throw this._error; + } - public get subscriptionPath(): never { - throw this._error; - } + public get subscriptionPath(): never { + throw this._error; + } - public get tenantId(): never { - throw this._error; - } + public get tenantId(): never { + throw this._error; + } - public get userId(): never { - throw this._error; - } + public get userId(): never { + throw this._error; + } - public get environment(): never { - throw this._error; - } + public get environment(): never { + throw this._error; + } - public get isCustomCloud(): never { - throw this._error; - } + public get isCustomCloud(): never { + throw this._error; + } } async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/tree/AzureAccountTreeItemWithAttached.ts b/Source/tree/AzureAccountTreeItemWithAttached.ts index ce1cdb8fd..172cd598f 100644 --- a/Source/tree/AzureAccountTreeItemWithAttached.ts +++ b/Source/tree/AzureAccountTreeItemWithAttached.ts @@ -3,49 +3,34 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureAccountTreeItemBase } from "@microsoft/vscode-azext-azureutils"; -import { - AzExtTreeItem, - IActionContext, - ISubscriptionContext, -} from "@microsoft/vscode-azext-utils"; -import { ext } from "../extensionVariables"; -import { AttachedAccountsTreeItem } from "./AttachedAccountsTreeItem"; -import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; +import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; +import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; +import { ext } from '../extensionVariables'; +import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; +import { SubscriptionTreeItem } from './SubscriptionTreeItem'; export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } + public constructor(testAccount?: {}) { + super(undefined, testAccount); + ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); + } - public createSubscriptionTreeItem( - root: ISubscriptionContext - ): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } + public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { + return new SubscriptionTreeItem(this, root); + } - public async loadMoreChildrenImpl( - clearCache: boolean, - context: IActionContext - ): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl( - clearCache, - context - ); - return children.concat(ext.attachedAccountsNode); - } + public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { + const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); + return children.concat(ext.attachedAccountsNode); + } - public compareChildrenImpl( - item1: AzExtTreeItem, - item2: AzExtTreeItem - ): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } + public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { + if (item1 instanceof AttachedAccountsTreeItem) { + return 1; + } else if (item2 instanceof AttachedAccountsTreeItem) { + return -1; + } else { + return super.compareChildrenImpl(item1, item2); + } + } } diff --git a/Source/tree/AzureDBAPIStep.ts b/Source/tree/AzureDBAPIStep.ts index a59ebfd48..8a11fdc95 100644 --- a/Source/tree/AzureDBAPIStep.ts +++ b/Source/tree/AzureDBAPIStep.ts @@ -3,103 +3,74 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VerifyProvidersStep } from "@microsoft/vscode-azext-azureutils"; -import { - AzureWizardExecuteStep, - AzureWizardPromptStep, - IAzureQuickPickItem, - IWizardOptions, -} from "@microsoft/vscode-azext-utils"; -import { - API, - Experience, - getExperienceQuickPicks, -} from "../AzureDBExperiences"; -import { PostgresServerType } from "../postgres/abstract/models"; -import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; -import { PostgresServerConfirmPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep"; -import { PostgresServerCreateStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep"; -import { PostgresServerCredPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep"; -import { PostgresServerCredUserStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep"; -import { PostgresServerNameStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerNameStep"; -import { PostgresServerSetCredentialsStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep"; -import { PostgresServerSkuStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep"; -import { localize } from "../utils/localize"; -import { CosmosDBAccountCapacityStep } from "./CosmosDBAccountWizard/CosmosDBAccountCapacityStep"; -import { CosmosDBAccountCreateStep } from "./CosmosDBAccountWizard/CosmosDBAccountCreateStep"; -import { CosmosDBAccountNameStep } from "./CosmosDBAccountWizard/CosmosDBAccountNameStep"; -import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; -import { IAzureDBWizardContext } from "./IAzureDBWizardContext"; +import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; +import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; +import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; +import { PostgresServerType } from '../postgres/abstract/models'; +import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; +import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; +import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; +import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; +import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; +import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; +import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; +import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; +import { localize } from '../utils/localize'; +import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; +import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; +import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; +import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; +import { IAzureDBWizardContext } from './IAzureDBWizardContext'; -export class AzureDBAPIStep extends AzureWizardPromptStep< - IPostgresServerWizardContext | ICosmosDBWizardContext -> { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = - getExperienceQuickPicks(); +export class AzureDBAPIStep extends AzureWizardPromptStep { + public async prompt(context: IAzureDBWizardContext): Promise { + const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); - const result: IAzureQuickPickItem = - await context.ui.showQuickPick(picks, { - placeHolder: localize( - "selectDBServerMsg", - "Select an Azure Database Server." - ), - }); + const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { + placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') + }); - context.defaultExperience = result.data; - } + context.defaultExperience = result.data; + } - public async getSubWizard( - context: IAzureDBWizardContext - ): Promise< - IWizardOptions - > { - let promptSteps: AzureWizardPromptStep< - IPostgresServerWizardContext | ICosmosDBWizardContext - >[]; - let executeSteps: AzureWizardExecuteStep< - IPostgresServerWizardContext | ICosmosDBWizardContext - >[]; - if ( - context.defaultExperience?.api === API.PostgresSingle || - context.defaultExperience?.api === API.PostgresFlexible - ) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = - PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = - PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(["Microsoft.DBforPostgreSQL"]), - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(["Microsoft.DocumentDB"]), - ]; - } - return { promptSteps, executeSteps }; - } + public async getSubWizard(context: IAzureDBWizardContext): Promise> { + let promptSteps: AzureWizardPromptStep[]; + let executeSteps: AzureWizardExecuteStep[]; + if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { + switch (context.defaultExperience?.api) { + case API.PostgresFlexible: + (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; + break; + case API.PostgresSingle: + (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; + break; + } + promptSteps = [ + new PostgresServerNameStep(), + new PostgresServerSkuStep(), + new PostgresServerCredUserStep(), + new PostgresServerCredPWStep(), + new PostgresServerConfirmPWStep(), + ]; + executeSteps = [ + new PostgresServerCreateStep(), + new PostgresServerSetCredentialsStep(), + new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) + ]; + } else { + promptSteps = [ + new CosmosDBAccountNameStep(), + new CosmosDBAccountCapacityStep(), + ]; + executeSteps = [ + new CosmosDBAccountCreateStep(), + new VerifyProvidersStep(['Microsoft.DocumentDB']) + ]; + } + return { promptSteps, executeSteps }; + } - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } + public shouldPrompt(context: IAzureDBWizardContext): boolean { + return !context.defaultExperience; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts index 192e5fa54..b46453e3a 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts @@ -3,53 +3,38 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzureWizardPromptStep, - IAzureQuickPickItem, -} from "@microsoft/vscode-azext-utils"; -import { localize } from "../../utils/localize"; -import { openUrl } from "../../utils/openUrl"; -import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; +import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../utils/localize'; +import { openUrl } from '../../utils/openUrl'; +import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { - public async prompt(context: ICosmosDBWizardContext): Promise { - const placeHolder: string = localize( - "selectDBServerMsg", - "Select a capacity model." - ); - const picks: IAzureQuickPickItem[] = [ - { - label: localize("provisionedOption", "Provisioned Throughput"), - data: false, - }, - { label: localize("serverlessOption", "Serverless"), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { - label: localize("learnMore", "$(link-external) Learn more..."), - data: undefined, - }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; - do { - pick = await context.ui.showQuickPick(picks, { - placeHolder, - suppressPersistence: true, - }); - if (pick === learnMore) { - await openUrl("https://aka.ms/cosmos-models"); - } - } while (pick === learnMore); + public async prompt(context: ICosmosDBWizardContext): Promise { - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data - ? "true" - : "false"; - } - } + const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') + const picks: IAzureQuickPickItem[] = [ + { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, + { label: localize('serverlessOption', 'Serverless'), data: true }, + ]; + const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; + picks.push(learnMore); + let pick: IAzureQuickPickItem; - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } + do { + pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); + if (pick === learnMore) { + await openUrl('https://aka.ms/cosmos-models'); + } + } while (pick === learnMore); + + if (pick.data) { + context.isServerless = pick.data; + context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; + } + } + + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return context.isServerless === undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts index f0eadf3a3..4bd469b84 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts @@ -3,81 +3,61 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountCreateUpdateParameters } from "@azure/arm-cosmosdb/src/models"; -import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from "vscode"; -import { SERVERLESS_CAPABILITY_NAME } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { createCosmosDBClient } from "../../utils/azureClients"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; +import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; +import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; +import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; +import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; +import { Progress } from 'vscode'; +import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { createCosmosDBClient } from '../../utils/azureClients'; +import { localize } from '../../utils/localize'; +import { nonNullProp } from '../../utils/nonNull'; +import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute( - context: ICosmosDBWizardContext, - progress: Progress<{ message?: string; increment?: number }> - ): Promise { - const locationName: string = ( - await LocationListStep.getLocation(context) - ).name; - const defaultExperience = nonNullProp(context, "defaultExperience"); - const rgName: string = nonNullProp( - nonNullProp(context, "resourceGroup"), - "name" - ); - const accountName = nonNullProp(context, "newServerName"); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize( - "creatingCosmosDBAccount", - 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', - accountName, - defaultExperience.shortName - ); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: "Standard", - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, "tag") }, - }; - - if (defaultExperience?.api === "MongoDB") { - options.apiProperties = { serverVersion: "3.6" }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = - await client.databaseAccounts.beginCreateOrUpdateAndWait( - rgName, - accountName, - options - ); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog( - `Successfully created Cosmos DB account "${accountName}".` - ); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } + public priority: number = 130; + + public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + const locationName: string = (await LocationListStep.getLocation(context)).name; + const defaultExperience = nonNullProp(context, 'defaultExperience'); + const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); + const accountName = nonNullProp(context, 'newServerName'); + + const client = await createCosmosDBClient(context); + const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); + ext.outputChannel.appendLog(creatingMessage); + progress.report({ message: creatingMessage }); + + const options: DatabaseAccountCreateUpdateParameters = { + location: locationName, + locations: [{ locationName: locationName }], + kind: defaultExperience.kind, + capabilities: [], + databaseAccountOfferType: 'Standard', + // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior + tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, + }; + + if (defaultExperience?.api === 'MongoDB') { + options.apiProperties = { serverVersion: '3.6' }; + } + + if (defaultExperience.capability) { + options.capabilities?.push({ name: defaultExperience.capability }); + } + + if (context.isServerless) { + options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); + } + + context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); + context.activityResult = context.databaseAccount as AppResource; + + ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); + } + + public shouldExecute(context: ICosmosDBWizardContext): boolean { + return !context.databaseAccount; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts index 222736605..87ef6be61 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts @@ -3,62 +3,47 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { - ResourceGroupListStep, - resourceGroupNamingRules, -} from "@microsoft/vscode-azext-azureutils"; -import { AzureNameStep } from "@microsoft/vscode-azext-utils"; -import { createCosmosDBClient } from "../../utils/azureClients"; -import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; +import { AzureNameStep } from '@microsoft/vscode-azext-utils'; +import { createCosmosDBClient } from '../../utils/azureClients'; +import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; export class CosmosDBAccountNameStep extends AzureNameStep { - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = ( - await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => - validateCosmosDBAccountName(name, client), - }) - ).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName( - context, - context.newServerName, - resourceGroupNamingRules - ); - } - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } + public async prompt(context: ICosmosDBWizardContext): Promise { + const client = await createCosmosDBClient(context); + context.newServerName = (await context.ui.showInputBox({ + placeHolder: "Account name", + prompt: "Provide a Cosmos DB account name", + validateInput: (name: string) => validateCosmosDBAccountName(name, client) + })).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); + } - protected async isRelatedNameAvailable( - context: ICosmosDBWizardContext, - name: string - ): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return !context.newServerName; + } + + protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validateCosmosDBAccountName( - name: string, - client: CosmosDBManagementClient -): Promise { - name = name ? name.trim() : ""; +async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { + name = name ? name.trim() : ''; - const min = 3; - const max = 31; + const min = 3; + const max = 31; - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } + if (name.length < min || name.length > max) { + return `The name must be between ${min} and ${max} characters.`; + } else if (name.match(/[^a-z0-9-]/)) { + return "The name can only contain lowercase letters, numbers, and the '-' character."; + } else if ((await client.databaseAccounts.checkNameExists(name)).body) { + return `Account name "${name}" is not available.`; + } else { + return undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts index cc12a75ed..61666a859 100644 --- a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb"; -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { IAzureDBWizardContext } from "../IAzureDBWizardContext"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; +import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; +import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; + +export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { + + /** + * The newly created Cosmos DB account + * This will be defined after `CosmosDBAccountStep.execute` occurs. + */ + databaseAccount?: DatabaseAccountGetResults; + isServerless?: boolean; -export interface ICosmosDBWizardContext - extends IAzureDBWizardContext, - ExecuteActivityContext { - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; } diff --git a/Source/tree/IAzureDBWizardContext.ts b/Source/tree/IAzureDBWizardContext.ts index 5f6946275..fd84ff0d5 100644 --- a/Source/tree/IAzureDBWizardContext.ts +++ b/Source/tree/IAzureDBWizardContext.ts @@ -3,10 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; -import { Experience } from "../AzureDBExperiences"; +import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; +import { Experience } from '../AzureDBExperiences'; export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - newServerName?: string; - defaultExperience?: Experience; + + newServerName?: string; + defaultExperience?: Experience; + } diff --git a/Source/tree/SubscriptionTreeItem.ts b/Source/tree/SubscriptionTreeItem.ts index 93cb2173a..910d8d970 100644 --- a/Source/tree/SubscriptionTreeItem.ts +++ b/Source/tree/SubscriptionTreeItem.ts @@ -3,322 +3,156 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { - DatabaseAccountGetResults, - DatabaseAccountListKeysResult, -} from "@azure/arm-cosmosdb/src/models"; -import { - getResourceGroupFromId, - ILocationWizardContext, - LocationListStep, - ResourceGroupListStep, - SubscriptionTreeItemBase, - uiUtils, -} from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - AzureWizard, - AzureWizardPromptStep, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { - API, - Experience, - getExperienceLabel, - tryGetExperience, -} from "../AzureDBExperiences"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; +import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; +import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from "../extensionVariables"; -import { tryGetGremlinEndpointFromAzure } from "../graph/gremlinEndpoints"; +import { ext } from '../extensionVariables'; +import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { - PostgresAbstractServer, - PostgresServerType, -} from "../postgres/abstract/models"; -import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; -import { - createPostgresConnectionString, - ParsedPostgresConnectionString, - parsePostgresConnectionString, -} from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; +import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; +import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; +import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; +import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; +import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from "../utils/activityUtils"; -import { - createCosmosDBClient, - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../utils/azureClients"; -import { localize } from "../utils/localize"; -import { nonNullProp } from "../utils/nonNull"; -import { AzureDBAPIStep } from "./AzureDBAPIStep"; -import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; +import { createActivityContext } from '../utils/activityUtils'; +import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; +import { localize } from '../utils/localize'; +import { nonNullProp } from '../utils/nonNull'; +import { AzureDBAPIStep } from './AzureDBAPIStep'; +import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = "Account"; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean, - context: IActionContext - ): Promise { - //Postgres - const postgresSingleClient = await createPostgreSQLClient([ - context, - this.subscription, - ]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([ - context, - this.subscription, - ]); - const postgresServers: PostgresAbstractServer[] = [ - ...( - await uiUtils.listAllIterator( - postgresSingleClient.servers.list() - ) - ).map((s) => - Object.assign(s, { serverType: PostgresServerType.Single }) - ), - ...( - await uiUtils.listAllIterator( - postgresFlexibleClient.servers.list() - ) - ).map((s) => - Object.assign(s, { serverType: PostgresServerType.Flexible }) - ), - ]; - - const treeItemPostgres: AzExtTreeItem[] = - await this.createTreeItemsWithErrorHandling( - postgresServers, - "invalidPostgreSQLAccount", - async (server: PostgresAbstractServer) => - await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator( - client.databaseAccounts.list() - ); - const treeItem: AzExtTreeItem[] = - await this.createTreeItemsWithErrorHandling( - accounts, - "invalidCosmosDBAccount", - async (db: DatabaseAccountGetResults) => - await SubscriptionTreeItem.initCosmosDBChild( - client, - db, - this - ), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild( - context: IActionContext & { defaultExperience?: Experience }, - node: SubscriptionTreeItem - ): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & - ICosmosDBWizardContext = Object.assign(context, node.subscription, { - ...(await createActivityContext()), - }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep(), - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize( - "createDBServerMsg", - "Create new Azure Database Server" - ), - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = - wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp( - wizardContext, - "newServerName" - ); - wizardContext.activityTitle = localize( - "createDBServerMsgActivityTitle", - 'Create new Azure Database Server "{0}"', - newServerName - ); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if ( - wizardContext.defaultExperience?.api === API.PostgresSingle || - wizardContext.defaultExperience?.api === API.PostgresFlexible - ) { - const createMessage: string = localize( - "createdServerOutput", - 'Successfully created PostgreSQL server "{0}".', - wizardContext.newServerName - ); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, "server"); - const host = nonNullProp(server, "fullyQualifiedDomainName"); - const username: string = - wizardContext.serverType === PostgresServerType.Flexible - ? nonNullProp(wizardContext, "shortUserName") - : nonNullProp(wizardContext, "longUserName"); - const password: string = nonNullProp( - wizardContext, - "adminPassword" - ); - const connectionString: string = createPostgresConnectionString( - host, - undefined, - username, - password - ); - const parsedCS: ParsedPostgresConnectionString = - parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild( - client, - nonNullProp(wizardContext, "databaseAccount"), - node - ); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return ( - typeof contextValue !== "string" || !/attached/i.test(contextValue) - ); - } - - public static async initCosmosDBChild( - client: CosmosDBManagementClient, - databaseAccount: DatabaseAccountGetResults, - parent: AzExtParentTreeItem - ): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, "id"); - const name: string = nonNullProp(databaseAccount, "name"); - const documentEndpoint: string = nonNullProp( - databaseAccount, - "documentEndpoint" - ); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = - name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings( - resourceGroup, - name - ); - const connectionString: URL = new URL( - nonNullProp( - nonNullProp(result, "connectionStrings")[0], - "connectionString" - ) - ); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = "retrywrites"; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, "false"); - } - - // Use the default connection string - return new MongoAccountTreeItem( - parent, - id, - label, - connectionString.toString(), - isEmulator, - databaseAccount - ); - } else { - const keyResult: DatabaseAccountListKeysResult = - await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp( - keyResult, - "primaryMasterKey" - ); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem( - parent, - id, - label, - documentEndpoint, - primaryMasterKey, - isEmulator, - databaseAccount - ); - case "Graph": { - const gremlinEndpoint = - await tryGetGremlinEndpointFromAzure( - client, - resourceGroup, - name - ); - return new GraphAccountTreeItem( - parent, - id, - label, - documentEndpoint, - gremlinEndpoint, - primaryMasterKey, - isEmulator, - databaseAccount - ); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem( - parent, - id, - label, - documentEndpoint, - primaryMasterKey, - isEmulator, - databaseAccount - ); - } - } - } - public static async initPostgresChild( - server: PostgresAbstractServer, - parent: AzExtParentTreeItem - ): Promise { - const connectionString: string = createPostgresConnectionString( - nonNullProp(server, "fullyQualifiedDomainName") - ); - const parsedCS: ParsedPostgresConnectionString = - parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } + public childTypeLabel: string = 'Account'; + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { + + //Postgres + const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); + const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); + const postgresServers: PostgresAbstractServer[] = [ + ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), + ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), + ]; + + const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( + postgresServers, + 'invalidPostgreSQLAccount', + async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), + (server: PostgresAbstractServer) => server.name + ); + + //CosmosDB + const client = await createCosmosDBClient([context, this]); + const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); + const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( + accounts, + 'invalidCosmosDBAccount', + async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), + (db: DatabaseAccountGetResults) => db.name + ); + + treeItem.push(...treeItemPostgres); + return treeItem; + } + + public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { + const client = await createCosmosDBClient([context, node.subscription]); + const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); + + const promptSteps: AzureWizardPromptStep[] = [ + new AzureDBAPIStep(), + new ResourceGroupListStep() + ]; + LocationListStep.addStep(wizardContext, promptSteps); + + const wizard = new AzureWizard(wizardContext, { + promptSteps, + executeSteps: [], + title: localize('createDBServerMsg', 'Create new Azure Database Server') + }); + + await wizard.prompt(); + + wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; + + const newServerName: string = nonNullProp(wizardContext, 'newServerName'); + wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); + + await wizard.execute(); + await ext.rgApi.appResourceTree.refresh(context); + if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { + const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); + const server = nonNullProp(wizardContext, 'server'); + const host = nonNullProp(server, 'fullyQualifiedDomainName'); + const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); + const password: string = nonNullProp(wizardContext, 'adminPassword'); + const connectionString: string = createPostgresConnectionString(host, undefined, username, password); + const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(node, parsedCS, server); + } else { + return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); + } + } + + public isAncestorOfImpl(contextValue: string | RegExp): boolean { + return typeof contextValue !== 'string' || !/attached/i.test(contextValue); + } + + public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { + const experience = tryGetExperience(databaseAccount); + const id: string = nonNullProp(databaseAccount, 'id'); + const name: string = nonNullProp(databaseAccount, 'name'); + const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); + + const resourceGroup: string = getResourceGroupFromId(id); + const accountKindLabel = getExperienceLabel(databaseAccount); + const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); + const isEmulator: boolean = false; + + if (experience && experience.api === "MongoDB") { + const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); + const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); + // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites + // but the newer node.js drivers started breaking this + const searchParam: string = 'retrywrites'; + if (!connectionString.searchParams.has(searchParam)) { + connectionString.searchParams.set(searchParam, 'false'); + } + + // Use the default connection string + return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); + } else { + const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); + const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); + switch (experience && experience.api) { + case "Table": + return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); + case "Graph": { + const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); + return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); + } + case "Core": + default: + // Default to DocumentDB, the base type for all Cosmos DB Accounts + return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); + + } + } + } + public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { + const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); + const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(parent, parsedCS, server); + } } diff --git a/Source/utils/InteractiveChildProcess.ts b/Source/utils/InteractiveChildProcess.ts index 1cd1848e5..26129b342 100644 --- a/Source/utils/InteractiveChildProcess.ts +++ b/Source/utils/InteractiveChildProcess.ts @@ -3,194 +3,174 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as cp from "child_process"; -import * as os from "os"; -import { isNumber } from "util"; -import * as vscode from "vscode"; -import { Event, EventEmitter } from "vscode"; -import { improveError } from "./improveError"; +import { parseError } from '@microsoft/vscode-azext-utils'; +import * as cp from 'child_process'; +import * as os from 'os'; +import { isNumber } from 'util'; +import * as vscode from 'vscode'; +import { Event, EventEmitter } from 'vscode'; +import { improveError } from './improveError'; // We add these when we display to the output window -const stdInPrefix = "> "; -const stdErrPrefix = "ERR> "; -const errorPrefix = "Error running process: "; +const stdInPrefix = '> '; +const stdErrPrefix = 'ERR> '; +const errorPrefix = 'Error running process: '; const processStartupTimeout = 60; export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; + command: string; + args: string[]; + outputChannel?: vscode.OutputChannel; + workingDirectory?: string; + showTimeInOutputChannel?: boolean; + outputFilterSearch?: RegExp; + outputFilterReplace?: string; } export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = - new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = - new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = - new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create( - options: IInteractiveChildProcessOptions - ): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess( - options - ); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(" "); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false, - }; - - this.writeLineToOutputChannel( - `Starting executable: "${this._options.command}" ${formattedArgs}` - ); - this._childProc = cp.spawn( - this._options.command, - this._options.args, - options - ); - - this._childProc.stdout?.on("data", (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on("data", (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on("error", (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on("close", (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel( - text: string, - displayPrefix?: string - ): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = - filteredText !== text && filteredText === ""; - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace( - this._options.outputFilterSearch, - this._options.outputFilterReplace || "" - ); - } - - return text; - } + private _childProc: cp.ChildProcess; + private readonly _options: IInteractiveChildProcessOptions; + private _startTime: number; + private _error: unknown; + private _isKilling: boolean; + + private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); + private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); + private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); + + private constructor(options: IInteractiveChildProcessOptions) { + this._options = options; + } + + public get onStdOut(): Event { + return this._onStdOutEmitter.event; + } + + public get onStdErr(): Event { + return this._onStdErrEmitter.event; + } + + public get onError(): Event { + return this._onErrorEmitter.event; + } + + public static async create(options: IInteractiveChildProcessOptions): Promise { + const child: InteractiveChildProcess = new InteractiveChildProcess(options); + await child.startCore(); + return child; + } + + public kill(): void { + this._isKilling = true; + this._childProc.kill(); + } + + public writeLine(text: string): void { + this.writeLineToOutputChannel(text, stdInPrefix); + this._childProc.stdin?.write(text + os.EOL); + } + + private async startCore(): Promise { + this._startTime = Date.now(); + const formattedArgs: string = this._options.args.join(' '); + + const workingDirectory = this._options.workingDirectory || os.tmpdir(); + const options: cp.SpawnOptions = { + cwd: workingDirectory, + + // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since + // the command is run in the shell, handling errors (such as command not found) would be more indirect, + // coming through STDERR instead of the error event + shell: false + }; + + this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); + this._childProc = cp.spawn(this._options.command, this._options.args, options); + + this._childProc.stdout?.on('data', (data: string | Buffer) => { + const text = data.toString(); + this._onStdOutEmitter.fire(text); + this.writeLineToOutputChannel(text); + }); + + this._childProc.stderr?.on('data', (data: string | Buffer) => { + const text = data.toString(); + this._onStdErrEmitter.fire(text); + this.writeLineToOutputChannel(text, stdErrPrefix); + }); + + this._childProc.on('error', (error: unknown) => { + const improvedError = improveError(error); + this.setError(improvedError); + }); + + this._childProc.on('close', (code: number | null) => { + if (isNumber(code) && code !== 0) { + this.setError(`The process exited with code ${code}.`); + } else if (!this._isKilling) { + this.setError(`The process exited prematurely.`); + } + }); + + // Wait for the process to start up + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + await new Promise(async (resolve, reject) => { + const started = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + if (!!this._error || this._isKilling) { + reject(this._error); + break; + } else if (this._childProc.pid) { + resolve(); + break; + } else { + if (Date.now() > started + processStartupTimeout) { + reject("The process did not start in a timely manner"); + break; + } + await delay(50); + } + } + }); + } + + private writeLineToOutputChannel(text: string, displayPrefix?: string): void { + const filteredText = this.filterText(text); + const changedIntoEmptyString = (filteredText !== text && filteredText === ''); + + if (!changedIntoEmptyString) { + text = filteredText; + if (this._options.outputChannel) { + if (this._options.showTimeInOutputChannel) { + const ms = Date.now() - this._startTime; + text = `${ms}ms: ${text}`; + } + + text = (displayPrefix || "") + text; + this._options.outputChannel.appendLine(text); + } + } + } + + private setError(error: unknown): void { + this.writeLineToOutputChannel(parseError(error).message, errorPrefix); + this._error = this._error || error; + this._onErrorEmitter.fire(error); + } + + private filterText(text: string): string { + if (this._options.outputFilterSearch) { + return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); + } + + return text; + } } async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/utils/activityUtils.ts b/Source/utils/activityUtils.ts index d90c436cd..fefd2fe00 100644 --- a/Source/utils/activityUtils.ts +++ b/Source/utils/activityUtils.ts @@ -8,13 +8,8 @@ import { ext } from "../extensionVariables"; import { getWorkspaceSetting } from "./settingUtils"; export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => - ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting( - "suppressActivityNotifications", - undefined, - "azureResourceGroups" - ), - }; + return { + registerActivity: async (activity) => ext.rgApi.registerActivity(activity), + suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), + }; } diff --git a/Source/utils/array.ts b/Source/utils/array.ts index 5d779a53a..06f095e8d 100644 --- a/Source/utils/array.ts +++ b/Source/utils/array.ts @@ -4,21 +4,11 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType( - arr: Object[] | undefined, - genericConstructor: new (...args: any[]) => T -): T[] { - return arr - ? arr.filter((element) => element instanceof genericConstructor) - : []; +export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { + return arr ? arr.filter(element => element instanceof genericConstructor) : []; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType( - arr: Object[] | undefined, - genericConstructor: new (...args: any[]) => T -): T | undefined { - return ( - arr && arr.find((element) => element instanceof genericConstructor) - ); +export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { + return arr && arr.find(element => element instanceof genericConstructor); } diff --git a/Source/utils/azureClients.ts b/Source/utils/azureClients.ts index c2f44bd1c..9be19e959 100644 --- a/Source/utils/azureClients.ts +++ b/Source/utils/azureClients.ts @@ -3,41 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { PostgreSQLManagementClient } from "@azure/arm-postgresql"; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; -import { - AzExtClientContext, - createAzureClient, -} from "@microsoft/vscode-azext-azureutils"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; +import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; +import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript -export async function createCosmosDBClient( - context: AzExtClientContext -): Promise { - return createAzureClient( - context, - (await import("@azure/arm-cosmosdb")).CosmosDBManagementClient - ); +export async function createCosmosDBClient(context: AzExtClientContext): Promise { + return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); } -export async function createPostgreSQLClient( - context: AzExtClientContext -): Promise { - return createAzureClient( - context, - (await import("@azure/arm-postgresql")).PostgreSQLManagementClient - ); +export async function createPostgreSQLClient(context: AzExtClientContext): Promise { + return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); } -export async function createPostgreSQLFlexibleClient( - context: AzExtClientContext -): Promise { - return createAzureClient( - context, - (await import("@azure/arm-postgresql-flexible")) - .PostgreSQLManagementClient - ); +export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { + return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); } diff --git a/Source/utils/azureUtils.ts b/Source/utils/azureUtils.ts index 0e067aa68..b0017314b 100644 --- a/Source/utils/azureUtils.ts +++ b/Source/utils/azureUtils.ts @@ -4,13 +4,11 @@ *--------------------------------------------------------------------------------------------*/ export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match( - /\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/ - ); + const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); - if (!matches || matches.length < 5) { - throw new Error("Invalid Azure Resource Id"); - } + if (!matches || matches.length < 5) { + throw new Error('Invalid Azure Resource Id'); + } - return matches[4]; + return matches[4]; } diff --git a/Source/utils/cp.ts b/Source/utils/cp.ts index 7f7d94117..660dc3068 100644 --- a/Source/utils/cp.ts +++ b/Source/utils/cp.ts @@ -3,15 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from "child_process"; +import * as cp from 'child_process'; -export async function commandSucceeds( - command: string, - ...args: string[] -): Promise { - return await new Promise((resolve) => { - cp.spawn(command, args) - .on("error", (_error) => resolve(false)) - .on("exit", (code) => resolve(code === 0)); - }); +export async function commandSucceeds(command: string, ...args: string[]): Promise { + return await new Promise(resolve => { + cp.spawn(command, args) + .on('error', _error => resolve(false)) + .on('exit', code => resolve(code === 0)); + }); } diff --git a/Source/utils/getIp.ts b/Source/utils/getIp.ts index d3085ea52..20d22e989 100644 --- a/Source/utils/getIp.ts +++ b/Source/utils/getIp.ts @@ -1,73 +1,61 @@ /*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from "@microsoft/vscode-azext-azureutils"; -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { isIPv4 } from "net"; -import { localize } from "./localize"; - -export function isIpInRanges( - ip: string, - ranges: { startIpAddress: string; endIpAddress: string }[] -): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ + +import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import { isIPv4 } from 'net'; +import { localize } from './localize'; + +export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { + const ipNum = ipToNum(ip); + return ranges.some((range) => { + const startIpNum = ipToNum(range.startIpAddress); + const endIpNum = ipToNum(range.endIpAddress); + return startIpNum <= ipNum && ipNum <= endIpNum; + }); } export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, "https://api.ipify.org/"), - () => getPublicIpv4Https(context, "https://ipv4.icanhazip.com/"), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; + const methods: (() => Promise)[] = [ + () => getPublicIpv4Https(context, 'https://api.ipify.org/'), + () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), + ]; + + let lastError: unknown; + for (const getIp of methods) { + try { + return await getIp(); + } catch (e: unknown) { + lastError = e; + } + } + + throw lastError; } -const failedToGetIp = localize("failedToGetIp", "Failed to get public IP"); +const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); function ipToNum(ip: string) { - return Number( - ip - .split(".") - .map((d) => ("000" + d).substring(-3)) - .join("") - ); + return Number( + ip.split(".") + .map(d => ("000" + d).substring(-3)) + .join("") + ); } -async function getPublicIpv4Https( - context: IActionContext, - url: string -): Promise { - const req = await sendRequestWithTimeout( - context, - { - method: "GET", - url, - }, - 5000, - undefined - ); +async function getPublicIpv4Https(context: IActionContext, url: string): Promise { + const req = await sendRequestWithTimeout(context, { + method: 'GET', + url, + }, 5000, undefined); - const ip = req.bodyAsText; + const ip = req.bodyAsText; - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } + if (!ip || !isIPv4(ip)) { + throw new Error(failedToGetIp); + } - return ip; + return ip; } diff --git a/Source/utils/getSecretStorageKey.ts b/Source/utils/getSecretStorageKey.ts index d04de6cea..8e404f554 100644 --- a/Source/utils/getSecretStorageKey.ts +++ b/Source/utils/getSecretStorageKey.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; + return `${serviceName}.${id}`; } diff --git a/Source/utils/improveError.ts b/Source/utils/improveError.ts index 08f0bedaf..27ff1f014 100644 --- a/Source/utils/improveError.ts +++ b/Source/utils/improveError.ts @@ -6,12 +6,12 @@ import { parseError } from "@microsoft/vscode-azext-utils"; export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } + const message = parseError(error).message; + // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" + const match = message.match(/spawn (.*) ENOENT/); + if (match) { + return new Error(`Could not find ${match[1]}`); + } - return error; + return error; } diff --git a/Source/utils/localize.ts b/Source/utils/localize.ts index 76d8fbf4d..2aee3fa12 100644 --- a/Source/utils/localize.ts +++ b/Source/utils/localize.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from "vscode-nls"; +import * as nls from 'vscode-nls'; export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Source/utils/nonNull.ts b/Source/utils/nonNull.ts index e9437afc9..d7104b4f8 100644 --- a/Source/utils/nonNull.ts +++ b/Source/utils/nonNull.ts @@ -3,52 +3,39 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { isNullOrUndefined } from "util"; +import { isNullOrUndefined } from 'util'; /** * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed * for the property and will give a compile error if the given name is not a property of the source. */ -export function nonNullProp( - source: TSource, - name: TKey -): NonNullable { - const value: NonNullable = >( - source[name] - ); - return nonNullValue(value, name); +export function nonNullProp(source: TSource, name: TKey): NonNullable { + const value: NonNullable = >source[name]; + return nonNullValue(value, name); } /** * Validates that a given value is not null and not undefined. */ -export function nonNullValue( - value: T | undefined | null, - propertyNameOrMessage?: string -): T { - if (isNullOrUndefined(value)) { - throw new Error( - "Internal error: Expected value to be neither null nor undefined" + - (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") - ); - } +export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { + if (isNullOrUndefined(value)) { + throw new Error( + 'Internal error: Expected value to be neither null nor undefined' + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); + } - return value; + return value; } /** * Validates that a given string is not null, undefined, nor empty */ -export function nonNullOrEmptyValue( - value: string | undefined, - propertyNameOrMessage?: string -): string { - if (!value) { - throw new Error( - "Internal error: Expected value to be neither null, undefined, nor empty" + - (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") - ); - } +export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { + if (!value) { + throw new Error( + 'Internal error: Expected value to be neither null, undefined, nor empty' + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); + } - return value; + return value; } diff --git a/Source/utils/openUrl.ts b/Source/utils/openUrl.ts index 5c7deaca7..0be3f5bbb 100644 --- a/Source/utils/openUrl.ts +++ b/Source/utils/openUrl.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as open from "open"; +import * as open from 'open'; export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); + // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 + // await vscode.env.openExternal(vscode.Uri.parse(url)); - await open(url); + await open(url); } diff --git a/Source/utils/randomUtils.ts b/Source/utils/randomUtils.ts index 1c4856b09..7a313f23a 100644 --- a/Source/utils/randomUtils.ts +++ b/Source/utils/randomUtils.ts @@ -6,15 +6,12 @@ import * as crypto from "crypto"; export namespace randomUtils { - export function getPseudononymousStringHash( - s: string, - encoding: crypto.BinaryToTextEncoding = "base64" - ): string { - return crypto.createHash("sha256").update(s).digest(encoding); - } + export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { + return crypto.createHash('sha256').update(s).digest(encoding); + } - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString("hex").slice(0, length); - } + export function getRandomHexString(length: number): string { + const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); + return buffer.toString('hex').slice(0, length); + } } diff --git a/Source/utils/settingUtils.ts b/Source/utils/settingUtils.ts index 0f75feb17..0ac1004c2 100644 --- a/Source/utils/settingUtils.ts +++ b/Source/utils/settingUtils.ts @@ -3,98 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ConfigurationTarget, - Uri, - workspace, - WorkspaceConfiguration, -} from "vscode"; +import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; import { ext } from "../extensionVariables"; /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateGlobalSetting( - section: string, - value: T, - prefix: string = ext.prefix -): Promise { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix); - await projectConfiguration.update( - section, - value, - ConfigurationTarget.Global - ); +export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); + await projectConfiguration.update(section, value, ConfigurationTarget.Global); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateWorkspaceSetting( - section: string, - value: T, - fsPath: string, - prefix: string = ext.prefix -): Promise { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); +export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); + await projectConfiguration.update(section, value); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getGlobalSetting( - key: string, - prefix: string = ext.prefix -): T | undefined { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = - projectConfiguration.inspect(key); - return result && result.globalValue; +export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); + const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); + return result && result.globalValue; } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSetting( - key: string, - fsPath?: string, - prefix: string = ext.prefix -): T | undefined { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration( - prefix, - fsPath ? Uri.file(fsPath) : undefined - ); - return projectConfiguration.get(key); +export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); + return projectConfiguration.get(key); } /** * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSettingFromAnyFolder( - key: string, - prefix: string = ext.prefix -): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = - projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } +export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { + if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { + let result: string | undefined; + for (const folder of workspace.workspaceFolders) { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); + const folderResult: string | undefined = projectConfiguration.get(key); + if (!result) { + result = folderResult; + } else if (folderResult && result !== folderResult) { + return undefined; + } + } + return result; + } else { + return getGlobalSetting(key, prefix); + } } diff --git a/Source/utils/timeout.ts b/Source/utils/timeout.ts index 1645f6d3f..cc5ffb2d6 100644 --- a/Source/utils/timeout.ts +++ b/Source/utils/timeout.ts @@ -8,50 +8,44 @@ const timedOutMessage = "Execution timed out"; /** * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. */ -export async function valueOnTimeout( - timeoutMs: number, - timeoutValue: T, - action: () => Promise | T -): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } +export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { + try { + return await rejectOnTimeout(timeoutMs, action); + } catch (err) { + const error = <{ message?: string }>err; + if (error && error.message === timedOutMessage) { + return timeoutValue; + } - throw err; - } + throw err; + } } /** * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. */ -export async function rejectOnTimeout( - timeoutMs: number, - action: () => Promise | T, - callerTimeOutMessage?: string -): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout(() => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, timeoutMs); +export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + return await new Promise(async (resolve, reject) => { + let timer: NodeJS.Timer | undefined = setTimeout( + () => { + timer = undefined; + reject(new Error(callerTimeOutMessage || timedOutMessage)); + }, + timeoutMs); - let value: T; - let error; + let value: T; + let error; - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); + try { + value = await action(); + clearTimeout(timer); + resolve(value); + } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + error = err; + clearTimeout(timer); + reject(error); + } + }); } diff --git a/Source/utils/vscodeUtils.ts b/Source/utils/vscodeUtils.ts index bdb5665b5..d05f84872 100644 --- a/Source/utils/vscodeUtils.ts +++ b/Source/utils/vscodeUtils.ts @@ -3,145 +3,101 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from "@azure/cosmos"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import * as fse from "fs-extra"; -import * as path from "path"; -import * as vscode from "vscode"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { ext } from "../extensionVariables"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { IMongoDocument } from "../mongo/tree/MongoDocumentTreeItem"; -import { getRootPath } from "./workspacUtils"; +import { ItemDefinition } from '@azure/cosmos'; +import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; +import { ext } from '../extensionVariables'; +import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; +import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; +import { getRootPath } from './workspacUtils'; export interface IDisposable { - dispose(): void; + dispose(): void; } export function dispose(disposables: T[]): T[] { - disposables.forEach((d) => d.dispose()); - return []; + disposables.forEach(d => d.dispose()); + return []; } export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; + return { dispose }; } -export async function showNewFile( - data: string, - fileName: string, - fileExtension: string, - column?: vscode.ViewColumn -): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName( - folderPath, - fileName, - fileExtension - ); - const uri: vscode.Uri = vscode.Uri.file( - path.join(folderPath, fullFileName) - ).with({ scheme: "untitled" }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument( - textDocument, - column - ? column > vscode.ViewColumn.Three - ? vscode.ViewColumn.One - : column - : undefined, - true - ); - await writeToEditor(editor, data); +export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { + const folderPath: string = getRootPath() || ext.context.extensionPath; + const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); + const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); + const textDocument = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); + await writeToEditor(editor, data); } -export async function writeToEditor( - editor: vscode.TextEditor, - data: string -): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt( - editor.document.lineCount - 1 - ); - editBuilder.delete( - new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position( - lastLine.range.start.line, - lastLine.range.end.character - ) - ) - ); - } +export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { + await editor.edit((editBuilder: vscode.TextEditorEdit) => { + if (editor.document.lineCount > 0) { + const lastLine = editor.document.lineAt(editor.document.lineCount - 1); + editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); + } - editBuilder.insert(new vscode.Position(0, 0), data); - }); + editBuilder.insert(new vscode.Position(0, 0), data); + }); } -async function getUniqueFileName( - folderPath: string, - fileName: string, - fileExtension: string -): Promise { - let count: number = 1; - const maxCount: number = 1024; +async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { + let count: number = 1; + const maxCount: number = 1024; - while (count < maxCount) { - const fileSuffix = count === 0 ? "" : "-" + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; + while (count < maxCount) { + const fileSuffix = count === 0 ? '' : '-' + count.toString(); + const fullFileName: string = fileName + fileSuffix + fileExtension; - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = - vscode.workspace.textDocuments.find( - (doc) => doc.uri.fsPath === fullPath - ) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } + const fullPath: string = path.join(folderPath, fullFileName); + const pathExists: boolean = await fse.pathExists(fullPath); + const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; + if (!pathExists && !editorExists) { + return fullFileName; + } + count += 1; + } - throw new Error("Could not find unique name for new file."); + throw new Error('Could not find unique name for new file.'); } export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join("/"); + const labels = [node.label]; + while (node.parent) { + node = node.parent; + labels.unshift(node.label); + if (isAccountTreeItem(node)) { + break; + } + } + return labels.join('/'); } function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return ( - treeItem instanceof MongoAccountTreeItem || - treeItem instanceof DocDBAccountTreeItemBase - ); + return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); } -export function getDocumentTreeItemLabel( - document: IMongoDocument | ItemDefinition -): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== "object") { - return String(value); - } - } - } - return String(document._id); +export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { + for (const field of getDocumentLabelFields()) { + // eslint-disable-next-line no-prototype-builtins + if (document.hasOwnProperty(field)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const value = document[field]; + if (value !== undefined && typeof value !== 'object') { + return String(value); + } + } + } + return String(document._id); } function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; + const settingKey: string = ext.settingsKeys.documentLabelFields; + return vscode.workspace.getConfiguration().get(settingKey) || []; } diff --git a/Source/utils/workspacUtils.ts b/Source/utils/workspacUtils.ts index 6892c2f6d..20b60da11 100644 --- a/Source/utils/workspacUtils.ts +++ b/Source/utils/workspacUtils.ts @@ -3,23 +3,16 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from "vscode"; -import { ext } from "../extensionVariables"; -import { nonNullValue } from "./nonNull"; +import * as vscode from 'vscode'; +import { ext } from '../extensionVariables'; +import { nonNullValue } from './nonNull'; export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && - vscode.workspace.workspaceFolders.length === 1 - ? vscode.workspace.workspaceFolders[0].uri.fsPath - : undefined; + // if this is a multi-root workspace, return undefined + return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; } export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = - vscode.workspace.getConfiguration(); - return nonNullValue( - config.get(ext.settingsKeys.batchSize), - "batchSize" - ); + const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); + return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); } diff --git a/Source/utils/wrapError.ts b/Source/utils/wrapError.ts index b82f638fd..f6ec5d2b5 100644 --- a/Source/utils/wrapError.ts +++ b/Source/utils/wrapError.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from "os"; +import * as os from 'os'; export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } + if (!innerError) { + return outerError; + } else if (!outerError) { + return innerError; + } - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } + const innerMessage = parseError(innerError).message; + const outerMessage = parseError(outerError).message; + if (outerError instanceof Error) { + outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; + return outerError; + } - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); + return new Error(`${outerMessage}${os.EOL}${innerMessage}`); } diff --git a/Source/vscode-cosmosdb.api.d.ts b/Source/vscode-cosmosdb.api.d.ts index 4e813c5e5..d5e4416c1 100644 --- a/Source/vscode-cosmosdb.api.d.ts +++ b/Source/vscode-cosmosdb.api.d.ts @@ -4,103 +4,93 @@ *--------------------------------------------------------------------------------------------*/ export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem( - query: TreeItemQuery - ): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem( - options: PickTreeItemOptions & { resourceType: "DatabaseAccount" } - ): Promise; - pickTreeItem( - options: PickTreeItemOptions & { resourceType: "Database" } - ): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; + apiVersion: string; + + /** + * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. + * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. + * + * @param query The query object to use for the find + */ + findTreeItem(query: TreeItemQuery): Promise; + + /** + * Prompts the user to pick an item from the Azure Databases tree + * + * @param options Configures the behavior of the tree item picker + */ + pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; + pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; + + /** + * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string + */ + revealTreeItem(resourceId: string): Promise; } export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; + /** + * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. + */ + reveal(): Promise; } export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - }; - - docDBData?: { - masterKey: string; - documentEndpoint: string; - }; - - postgresData?: { - username: string | undefined; - password: string | undefined; - }; + hostName: string; + port: string; + connectionString: string; + + /** + * Data specific to Azure or undefined if the resource is not in Azure. + */ + azureData?: { + accountName: string; + accountId: string; + } + + docDBData?: { + masterKey: string; + documentEndpoint: string; + } + + postgresData?: { + username: string | undefined; + password: string | undefined; + } + } export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; + databaseName: string; } -export type AzureDatabasesResourceType = "DatabaseAccount" | "Database"; +export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; -export type AzureDatabasesApiType = - | "Mongo" - | "SQL" - | "Graph" - | "Table" - | "Postgres"; +export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; + /** + * The resource type of the picked item + */ + resourceType: AzureDatabasesResourceType; + + /** + * An array of the API types that can be picked, or undefined if all API types are allowed + */ + apiType?: AzureDatabasesApiType[]; } export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - }; + /** + * An account or database connection string + */ + connectionString?: string; + + postgresData?: { + hostName: string; + port: string; + databaseName: string | undefined; + username: string | undefined; + password: string | undefined; + } } diff --git a/Source/vscode-cosmosdbgraph.api.d.ts b/Source/vscode-cosmosdbgraph.api.d.ts index bf8d4c769..95cde2531 100644 --- a/Source/vscode-cosmosdbgraph.api.d.ts +++ b/Source/vscode-cosmosdbgraph.api.d.ts @@ -4,26 +4,26 @@ *--------------------------------------------------------------------------------------------*/ export interface CosmosDBGraphExtensionApi { - apiVersion: string; + apiVersion: string; - openGraphExplorer(config: IGraphConfiguration): Promise; + openGraphExplorer(config: IGraphConfiguration): Promise; } export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; + host: string; + port: number; + ssl: boolean; } export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; + // e.g. https://graphaccount.documents.azure.com:443 + documentEndpoint: string; - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; + gremlinEndpoint?: IGremlinEndpoint; + possibleGremlinEndpoints: IGremlinEndpoint[]; - key: string; - databaseName: string; - graphName: string; - tabTitle: string; + key: string; + databaseName: string; + graphName: string; + tabTitle: string; } From c2eb70212dbf19b6fa0815711ccfc57dfbb0b074 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Tue, 14 Nov 2023 22:41:44 +0200 Subject: [PATCH 12/33] squash! --- src/AzureDBExperiences.ts | 118 -- src/DatabasesFileSystem.ts | 77 - src/ParsedConnectionString.ts | 28 - src/azureAccountUtils.ts | 31 - .../api/DatabaseAccountTreeItemInternal.ts | 106 -- src/commands/api/DatabaseTreeItemInternal.ts | 42 - src/commands/api/apiCache.ts | 46 - src/commands/api/findTreeItem.ts | 146 -- src/commands/api/pickTreeItem.ts | 100 -- src/commands/api/revealTreeItem.ts | 16 - .../DatabaseAccountDeleteStep.ts | 19 - .../IDeleteWizardContext.ts | 13 - .../deleteCosmosDBAccount.ts | 32 - .../deleteDatabaseAccount.ts | 37 - src/commands/importDocuments.ts | 163 -- src/constants.ts | 136 -- src/docdb/docDBConnectionStrings.ts | 42 - src/docdb/getCosmosClient.ts | 19 - src/docdb/registerDocDBCommands.ts | 104 -- src/docdb/tree/DocDBAccountTreeItem.ts | 37 - src/docdb/tree/DocDBAccountTreeItemBase.ts | 95 -- src/docdb/tree/DocDBCollectionTreeItem.ts | 92 -- src/docdb/tree/DocDBDatabaseTreeItem.ts | 22 - src/docdb/tree/DocDBDatabaseTreeItemBase.ts | 161 -- src/docdb/tree/DocDBDocumentTreeItem.ts | 133 -- src/docdb/tree/DocDBDocumentsTreeItem.ts | 129 -- .../tree/DocDBStoredProcedureTreeItem.ts | 76 - .../tree/DocDBStoredProceduresTreeItem.ts | 97 -- src/docdb/tree/DocDBTreeItemBase.ts | 55 - src/docdb/tree/DocDBUtils.ts | 12 - src/docdb/tree/IDocDBTreeRoot.ts | 14 - src/extension.ts | 215 --- src/extensionVariables.ts | 51 - src/getExtensionApi.ts | 31 - src/graph/gremlinEndpoints.ts | 47 - src/graph/registerGraphCommands.ts | 62 - src/graph/tree/GraphAccountTreeItem.ts | 45 - src/graph/tree/GraphCollectionTreeItem.ts | 87 - src/graph/tree/GraphDatabaseTreeItem.ts | 65 - src/graph/tree/GraphTreeItem.ts | 56 - src/mongo/MongoCommand.ts | 24 - src/mongo/MongoScrapbook.ts | 491 ------ src/mongo/MongoShell.ts | 187 --- src/mongo/connectToMongoClient.ts | 49 - src/mongo/errorListeners.ts | 67 - src/mongo/grammar/mongo.tokens | 36 - src/mongo/grammar/mongoLexer.tokens | 36 - src/mongo/grammar/mongoLexer.ts | 247 --- src/mongo/grammar/mongoListener.ts | 208 --- src/mongo/grammar/mongoParser.ts | 1466 ----------------- src/mongo/grammar/mongoVisitor.ts | 143 -- src/mongo/grammar/visitors.ts | 83 - src/mongo/languageClient.ts | 58 - src/mongo/languageServer.ts | 31 - src/mongo/mongoConnectionStrings.ts | 104 -- src/mongo/registerMongoCommands.ts | 223 --- src/mongo/services/IConnectionParams.ts | 10 - src/mongo/services/MongoCodeLensProvider.ts | 75 - src/mongo/services/completionItemProvider.ts | 439 ----- src/mongo/services/languageService.ts | 90 - src/mongo/services/mongoScript.ts | 101 -- src/mongo/services/schemaService.ts | 628 ------- src/mongo/setConnectedNode.ts | 13 - src/mongo/tree/IMongoTreeRoot.ts | 9 - src/mongo/tree/MongoAccountTreeItem.ts | 140 -- src/mongo/tree/MongoCollectionTreeItem.ts | 320 ---- src/mongo/tree/MongoDatabaseTreeItem.ts | 258 --- src/mongo/tree/MongoDocumentTreeItem.ts | 97 -- .../abstract/AbstractPostgresClient.ts | 23 - src/postgres/abstract/models.ts | 55 - src/postgres/commands/checkAuthentication.ts | 36 - .../commands/configurePostgresFirewall.ts | 69 - .../commands/connectPostgresDatabase.ts | 39 - src/postgres/commands/copyConnectionString.ts | 36 - .../commands/createPostgresDatabase.ts | 26 - .../IPostgresQueryWizardContext.ts | 12 - .../IPostgresFunctionQueryWizardContext.ts | 10 - .../function/createPostgresFunctionQuery.ts | 23 - .../function/steps/FunctionQueryCreateStep.ts | 31 - .../FunctionQueryCustomReturnTypeStep.ts | 18 - .../function/steps/FunctionQueryNameStep.ts | 22 - .../steps/FunctionQueryReturnTypeStep.ts | 50 - .../runPostgresQueryWizard.ts | 23 - .../createPostgresStoredProcedureQuery.ts | 20 - .../steps/StoredProcedureQueryCreateStep.ts | 30 - .../steps/StoredProcedureQueryNameStep.ts | 22 - .../createPostgresQuery/validateIdentifier.ts | 113 -- .../IPostgresServerWizardContext.ts | 24 - .../steps/PostgresServerConfirmPWStep.ts | 31 - .../steps/PostgresServerCreateStep.ts | 104 -- .../steps/PostgresServerCredPWStep.ts | 53 - .../steps/PostgresServerCredUserStep.ts | 48 - .../steps/PostgresServerNameStep.ts | 60 - .../steps/PostgresServerSetCredentialsStep.ts | 46 - .../steps/PostgresServerSkuStep.ts | 250 --- .../commands/deletePostgresDatabase.ts | 30 - .../commands/deletePostgresFunction.ts | 29 - src/postgres/commands/deletePostgresServer.ts | 22 - .../commands/deletePostgresStoredProcedure.ts | 29 - src/postgres/commands/deletePostgresTable.ts | 28 - .../commands/enterPostgresCredentials.ts | 85 - .../executePostgresQueryInDocument.ts | 65 - src/postgres/commands/openPostgresFunction.ts | 21 - .../commands/openPostgresStoredProcedure.ts | 21 - .../commands/registerPostgresCommands.ts | 82 - .../commands/setPostgresCredentials.ts | 32 - src/postgres/getClientConfig.ts | 172 -- src/postgres/getPostgresProcedureQueryRows.ts | 58 - src/postgres/getTables.ts | 34 - src/postgres/postgresConnectionStrings.ts | 74 - src/postgres/postgresConstants.ts | 8 - src/postgres/runPostgresQuery.ts | 19 - .../services/PostgresCodeLensProvider.ts | 66 - src/postgres/showPostgresQuery.ts | 14 - src/postgres/tree/ClientConfigFactory.ts | 86 - src/postgres/tree/PostgresColumnTreeItem.ts | 33 - src/postgres/tree/PostgresDatabaseTreeItem.ts | 115 -- src/postgres/tree/PostgresFunctionTreeItem.ts | 48 - .../tree/PostgresFunctionsTreeItem.ts | 46 - .../tree/PostgresResourcesTreeItemBase.ts | 27 - src/postgres/tree/PostgresServerTreeItem.ts | 252 --- .../tree/PostgresStoredProcedureTreeItem.ts | 48 - .../tree/PostgresStoredProceduresTreeItem.ts | 46 - src/postgres/tree/PostgresTableTreeItem.ts | 56 - src/postgres/tree/PostgresTablesTreeItem.ts | 51 - src/resolver/AppResolver.ts | 71 - src/resolver/DatabaseWorkspaceProvider.ts | 33 - .../ResolvedDatabaseAccountResource.ts | 57 - src/resolver/ResolvedDocDBAccountResource.ts | 32 - src/resolver/ResolvedMongoAccountResource.ts | 20 - .../ResolvedPostgresServerResource.ts | 48 - src/table/tree/TableAccountTreeItem.ts | 39 - src/tree/AttachedAccountsTreeItem.ts | 420 ----- src/tree/AzureAccountTreeItemWithAttached.ts | 36 - src/tree/AzureDBAPIStep.ts | 76 - .../CosmosDBAccountCapacityStep.ts | 40 - .../CosmosDBAccountCreateStep.ts | 63 - .../CosmosDBAccountNameStep.ts | 49 - .../ICosmosDBWizardContext.ts | 19 - src/tree/IAzureDBWizardContext.ts | 14 - src/tree/SubscriptionTreeItem.ts | 158 -- src/utils/InteractiveChildProcess.ts | 176 -- src/utils/activityUtils.ts | 15 - src/utils/array.ts | 14 - src/utils/azureClients.ts | 24 - src/utils/azureUtils.ts | 14 - src/utils/cp.ts | 14 - src/utils/getIp.ts | 61 - src/utils/getSecretStorageKey.ts | 8 - src/utils/improveError.ts | 17 - src/utils/localize.ts | 8 - src/utils/nonNull.ts | 41 - src/utils/openUrl.ts | 13 - src/utils/randomUtils.ts | 17 - src/utils/settingUtils.ts | 62 - src/utils/timeout.ts | 51 - src/utils/vscodeUtils.ts | 103 -- src/utils/workspacUtils.ts | 18 - src/utils/wrapError.ts | 24 - src/vscode-cosmosdb.api.d.ts | 96 -- src/vscode-cosmosdbgraph.api.d.ts | 29 - 161 files changed, 13441 deletions(-) delete mode 100644 src/AzureDBExperiences.ts delete mode 100644 src/DatabasesFileSystem.ts delete mode 100644 src/ParsedConnectionString.ts delete mode 100644 src/azureAccountUtils.ts delete mode 100644 src/commands/api/DatabaseAccountTreeItemInternal.ts delete mode 100644 src/commands/api/DatabaseTreeItemInternal.ts delete mode 100644 src/commands/api/apiCache.ts delete mode 100644 src/commands/api/findTreeItem.ts delete mode 100644 src/commands/api/pickTreeItem.ts delete mode 100644 src/commands/api/revealTreeItem.ts delete mode 100644 src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts delete mode 100644 src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts delete mode 100644 src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts delete mode 100644 src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts delete mode 100644 src/commands/importDocuments.ts delete mode 100644 src/constants.ts delete mode 100644 src/docdb/docDBConnectionStrings.ts delete mode 100644 src/docdb/getCosmosClient.ts delete mode 100644 src/docdb/registerDocDBCommands.ts delete mode 100644 src/docdb/tree/DocDBAccountTreeItem.ts delete mode 100644 src/docdb/tree/DocDBAccountTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBCollectionTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDatabaseTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDatabaseTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBDocumentTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDocumentsTreeItem.ts delete mode 100644 src/docdb/tree/DocDBStoredProcedureTreeItem.ts delete mode 100644 src/docdb/tree/DocDBStoredProceduresTreeItem.ts delete mode 100644 src/docdb/tree/DocDBTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBUtils.ts delete mode 100644 src/docdb/tree/IDocDBTreeRoot.ts delete mode 100644 src/extension.ts delete mode 100644 src/extensionVariables.ts delete mode 100644 src/getExtensionApi.ts delete mode 100644 src/graph/gremlinEndpoints.ts delete mode 100644 src/graph/registerGraphCommands.ts delete mode 100644 src/graph/tree/GraphAccountTreeItem.ts delete mode 100644 src/graph/tree/GraphCollectionTreeItem.ts delete mode 100644 src/graph/tree/GraphDatabaseTreeItem.ts delete mode 100644 src/graph/tree/GraphTreeItem.ts delete mode 100644 src/mongo/MongoCommand.ts delete mode 100644 src/mongo/MongoScrapbook.ts delete mode 100644 src/mongo/MongoShell.ts delete mode 100644 src/mongo/connectToMongoClient.ts delete mode 100644 src/mongo/errorListeners.ts delete mode 100644 src/mongo/grammar/mongo.tokens delete mode 100644 src/mongo/grammar/mongoLexer.tokens delete mode 100644 src/mongo/grammar/mongoLexer.ts delete mode 100644 src/mongo/grammar/mongoListener.ts delete mode 100644 src/mongo/grammar/mongoParser.ts delete mode 100644 src/mongo/grammar/mongoVisitor.ts delete mode 100644 src/mongo/grammar/visitors.ts delete mode 100644 src/mongo/languageClient.ts delete mode 100644 src/mongo/languageServer.ts delete mode 100644 src/mongo/mongoConnectionStrings.ts delete mode 100644 src/mongo/registerMongoCommands.ts delete mode 100644 src/mongo/services/IConnectionParams.ts delete mode 100644 src/mongo/services/MongoCodeLensProvider.ts delete mode 100644 src/mongo/services/completionItemProvider.ts delete mode 100644 src/mongo/services/languageService.ts delete mode 100644 src/mongo/services/mongoScript.ts delete mode 100644 src/mongo/services/schemaService.ts delete mode 100644 src/mongo/setConnectedNode.ts delete mode 100644 src/mongo/tree/IMongoTreeRoot.ts delete mode 100644 src/mongo/tree/MongoAccountTreeItem.ts delete mode 100644 src/mongo/tree/MongoCollectionTreeItem.ts delete mode 100644 src/mongo/tree/MongoDatabaseTreeItem.ts delete mode 100644 src/mongo/tree/MongoDocumentTreeItem.ts delete mode 100644 src/postgres/abstract/AbstractPostgresClient.ts delete mode 100644 src/postgres/abstract/models.ts delete mode 100644 src/postgres/commands/checkAuthentication.ts delete mode 100644 src/postgres/commands/configurePostgresFirewall.ts delete mode 100644 src/postgres/commands/connectPostgresDatabase.ts delete mode 100644 src/postgres/commands/copyConnectionString.ts delete mode 100644 src/postgres/commands/createPostgresDatabase.ts delete mode 100644 src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/validateIdentifier.ts delete mode 100644 src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts delete mode 100644 src/postgres/commands/deletePostgresDatabase.ts delete mode 100644 src/postgres/commands/deletePostgresFunction.ts delete mode 100644 src/postgres/commands/deletePostgresServer.ts delete mode 100644 src/postgres/commands/deletePostgresStoredProcedure.ts delete mode 100644 src/postgres/commands/deletePostgresTable.ts delete mode 100644 src/postgres/commands/enterPostgresCredentials.ts delete mode 100644 src/postgres/commands/executePostgresQueryInDocument.ts delete mode 100644 src/postgres/commands/openPostgresFunction.ts delete mode 100644 src/postgres/commands/openPostgresStoredProcedure.ts delete mode 100644 src/postgres/commands/registerPostgresCommands.ts delete mode 100644 src/postgres/commands/setPostgresCredentials.ts delete mode 100644 src/postgres/getClientConfig.ts delete mode 100644 src/postgres/getPostgresProcedureQueryRows.ts delete mode 100644 src/postgres/getTables.ts delete mode 100644 src/postgres/postgresConnectionStrings.ts delete mode 100644 src/postgres/postgresConstants.ts delete mode 100644 src/postgres/runPostgresQuery.ts delete mode 100644 src/postgres/services/PostgresCodeLensProvider.ts delete mode 100644 src/postgres/showPostgresQuery.ts delete mode 100644 src/postgres/tree/ClientConfigFactory.ts delete mode 100644 src/postgres/tree/PostgresColumnTreeItem.ts delete mode 100644 src/postgres/tree/PostgresDatabaseTreeItem.ts delete mode 100644 src/postgres/tree/PostgresFunctionTreeItem.ts delete mode 100644 src/postgres/tree/PostgresFunctionsTreeItem.ts delete mode 100644 src/postgres/tree/PostgresResourcesTreeItemBase.ts delete mode 100644 src/postgres/tree/PostgresServerTreeItem.ts delete mode 100644 src/postgres/tree/PostgresStoredProcedureTreeItem.ts delete mode 100644 src/postgres/tree/PostgresStoredProceduresTreeItem.ts delete mode 100644 src/postgres/tree/PostgresTableTreeItem.ts delete mode 100644 src/postgres/tree/PostgresTablesTreeItem.ts delete mode 100644 src/resolver/AppResolver.ts delete mode 100644 src/resolver/DatabaseWorkspaceProvider.ts delete mode 100644 src/resolver/ResolvedDatabaseAccountResource.ts delete mode 100644 src/resolver/ResolvedDocDBAccountResource.ts delete mode 100644 src/resolver/ResolvedMongoAccountResource.ts delete mode 100644 src/resolver/ResolvedPostgresServerResource.ts delete mode 100644 src/table/tree/TableAccountTreeItem.ts delete mode 100644 src/tree/AttachedAccountsTreeItem.ts delete mode 100644 src/tree/AzureAccountTreeItemWithAttached.ts delete mode 100644 src/tree/AzureDBAPIStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts delete mode 100644 src/tree/IAzureDBWizardContext.ts delete mode 100644 src/tree/SubscriptionTreeItem.ts delete mode 100644 src/utils/InteractiveChildProcess.ts delete mode 100644 src/utils/activityUtils.ts delete mode 100644 src/utils/array.ts delete mode 100644 src/utils/azureClients.ts delete mode 100644 src/utils/azureUtils.ts delete mode 100644 src/utils/cp.ts delete mode 100644 src/utils/getIp.ts delete mode 100644 src/utils/getSecretStorageKey.ts delete mode 100644 src/utils/improveError.ts delete mode 100644 src/utils/localize.ts delete mode 100644 src/utils/nonNull.ts delete mode 100644 src/utils/openUrl.ts delete mode 100644 src/utils/randomUtils.ts delete mode 100644 src/utils/settingUtils.ts delete mode 100644 src/utils/timeout.ts delete mode 100644 src/utils/vscodeUtils.ts delete mode 100644 src/utils/workspacUtils.ts delete mode 100644 src/utils/wrapError.ts delete mode 100644 src/vscode-cosmosdb.api.d.ts delete mode 100644 src/vscode-cosmosdbgraph.api.d.ts diff --git a/src/AzureDBExperiences.ts b/src/AzureDBExperiences.ts deleted file mode 100644 index be9765dc6..000000000 --- a/src/AzureDBExperiences.ts +++ /dev/null @@ -1,118 +0,0 @@ -/* ------------------------------------------------------------------------------------------ - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { nonNullProp } from './utils/nonNull'; - -export enum API { - MongoDB = 'MongoDB', - Graph = 'Graph', - Table = 'Table', - Core = 'Core', - PostgresSingle = 'PostgresSingle', - PostgresFlexible = 'PostgresFlexible' -} - -export enum DBAccountKind { - MongoDB = 'MongoDB', - GlobalDocumentDB = 'GlobalDocumentDB' -} - -export type CapabilityName = 'EnableGremlin' | 'EnableTable'; - -export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; - } - return info; -} - -export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { - - const experience: Experience | undefined = tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); - const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); - return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); - -} - -export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { - return GremlinExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; -} - -export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; - - longName: string; - shortName: string; - description?: string; - - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; - - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; -} - -export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } -} - -export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } -} - -export function getExperienceQuickPick(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; -} - -export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; -} - -// Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" -// Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; -export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; -export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; -export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; -const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; -const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; - -const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; -const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; -const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); diff --git a/src/DatabasesFileSystem.ts b/src/DatabasesFileSystem.ts deleted file mode 100644 index 93c2b4938..000000000 --- a/src/DatabasesFileSystem.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; -import { FileChangeType } from "vscode-languageclient"; -import { ext } from "./extensionVariables"; -import { localize } from "./utils/localize"; -import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; -import { getNodeEditorLabel } from "./utils/vscodeUtils"; - -export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; -} - -export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = 'azureDatabases'; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; - - public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { - const size: number = Buffer.byteLength(await node.getFileContent(context)); - return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; - } - - public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { - return Buffer.from(await node.getFileContent(context)); - } - - public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { - const showSavePromptKey: string = 'showSavePrompt'; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = 'cosmosDB'; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { - const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); - const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError('dontUpload'); - } - } - - await node.writeFileContent(context, content.toString()); - await node.refresh(context); - - const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); - ext.outputChannel.appendLog(updatedMessage); - } - - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } - - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } - - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } -} diff --git a/src/ParsedConnectionString.ts b/src/ParsedConnectionString.ts deleted file mode 100644 index 99654ef5a..000000000 --- a/src/ParsedConnectionString.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; - - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; - - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } - - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } - - public get fullId(): string { - return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; - } -} diff --git a/src/azureAccountUtils.ts b/src/azureAccountUtils.ts deleted file mode 100644 index 7f37da4cd..000000000 --- a/src/azureAccountUtils.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtServiceClientCredentials } from "@microsoft/vscode-azext-utils"; -import { getApiExport } from "./getExtensionApi"; - -const azureAccountExtensionId = "ms-vscode.azure-account"; - -type AzureSession = { - userId: string; -}; - -/** - * @returns The user session of the signed-in azure account. - */ -export async function getAzureAdUserSession(): Promise { - const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; -} - -/** - * Gets a function that can request an access token for a specified scope for the signed-in azure account. - */ -export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { - return async () => { - const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; - return getTokenResult?.token ?? ""; - }; -} diff --git a/src/commands/api/DatabaseAccountTreeItemInternal.ts b/src/commands/api/DatabaseAccountTreeItemInternal.ts deleted file mode 100644 index 89a8c1164..000000000 --- a/src/commands/api/DatabaseAccountTreeItemInternal.ts +++ /dev/null @@ -1,106 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { API } from '../../AzureDBExperiences'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; - -export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { - protected _parsedCS: ParsedConnectionString; - private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; - - constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } - - public get connectionString(): string { - return this._parsedCS.connectionString; - } - - public get hostName(): string { - return this._parsedCS.hostName; - } - - public get port(): string { - return this._parsedCS.port; - } - - public get azureData(): { accountName: string, accountId: string } | undefined { - if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), - accountId: this._accountNode.fullId - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId - }; - } - } - return undefined; - } - - public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey - }; - } else { - return undefined; - } - } - - public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password - }; - } else { - return undefined; - } - } - - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); - }); - } - - protected async getAccountNode(context: IActionContext): Promise { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { - - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); - } - - return this._accountNode; - } -} diff --git a/src/commands/api/DatabaseTreeItemInternal.ts b/src/commands/api/DatabaseTreeItemInternal.ts deleted file mode 100644 index 9d6b0d140..000000000 --- a/src/commands/api/DatabaseTreeItemInternal.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; - -export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; - - constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } - - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); - } - - await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); - }); - } -} diff --git a/src/commands/api/apiCache.ts b/src/commands/api/apiCache.ts deleted file mode 100644 index 30da342aa..000000000 --- a/src/commands/api/apiCache.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; - -/** - * This cache is used to speed up api calls from other extensions to the Cosmos DB extension - * For now, it only helps on a per-session basis - */ -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = new Map(); - -export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { - sessionCache.set(parsedCS.fullId, treeItem); -} - -export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); -} - -export function removeTreeItemFromCache(expected: ParsedConnectionString): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); - } else { - actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); - } - if (actual && (actual.accountId === expected.accountId)) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } -} diff --git a/src/commands/api/findTreeItem.ts b/src/commands/api/findTreeItem.ts deleted file mode 100644 index 088413e52..000000000 --- a/src/commands/api/findTreeItem.ts +++ /dev/null @@ -1,146 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -export async function findTreeItem(query: TreeItemQuery): Promise { - return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, 'connectionString'); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = await rootNode.getCachedChildren(context); - result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - }); -} - -async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); - } - if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); - } else { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); - } - - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); - } else { - return new DatabaseAccountTreeItemInternal(expected, dbAccount); - } - - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; -} diff --git a/src/commands/api/pickTreeItem.ts b/src/commands/api/pickTreeItem.ts deleted file mode 100644 index dc84ce55a..000000000 --- a/src/commands/api/pickTreeItem.ts +++ /dev/null @@ -1,100 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; -import { databaseAccountType } from '../../constants'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { localize } from '../../utils/localize'; -import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; -function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case 'Mongo': - return MongoDatabaseTreeItem.contextValue; - case 'SQL': - return DocDBDatabaseTreeItem.contextValue; - case 'Graph': - return GraphDatabaseTreeItem.contextValue; - case 'Postgres': - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } -} - - -export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { - return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case 'Database': - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType ? - pickTreeOptions.apiType.map(getDatabaseContextValue) : - databaseContextValues; - break; - case 'DatabaseAccount': - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); - } - - const pickedItem = await ext.rgApi.pickAppResource(context, options); - - let parsedCS: ParsedConnectionString; - let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; - let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); - } - - const result = databaseNode ? - new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : - new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - }); -} diff --git a/src/commands/api/revealTreeItem.ts b/src/commands/api/revealTreeItem.ts deleted file mode 100644 index d13589351..000000000 --- a/src/commands/api/revealTreeItem.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { ext } from "../../extensionVariables"; - -export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); - } - }); -} diff --git a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts deleted file mode 100644 index 1ef9ca645..000000000 --- a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; - -export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } - - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } -} diff --git a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts deleted file mode 100644 index 762beb96e..000000000 --- a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; - -export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; -} diff --git a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts deleted file mode 100644 index a90956b30..000000000 --- a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; -import { localize } from '../../utils/localize'; -import { IDeleteWizardContext } from './IDeleteWizardContext'; - -export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await deletePromise; - const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } else { - await deletePromise; - } -} diff --git a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts deleted file mode 100644 index 4792710d4..000000000 --- a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; -import { createActivityContext } from "../../utils/activityUtils"; -import { localize } from "../../utils/localize"; -import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; - - -export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()) - }); - - const title = wizardContext.deletePostgres ? - localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : - localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) - - const confirmationMessage = wizardContext.deletePostgres ? - localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : - localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); - - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()] - }); - - await wizard.prompt(); - await wizard.execute(); -} diff --git a/src/commands/importDocuments.ts b/src/commands/importDocuments.ts deleted file mode 100644 index bd4c83e3f..000000000 --- a/src/commands/importDocuments.ts +++ /dev/null @@ -1,163 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ItemDefinition } from '@azure/cosmos'; -import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { cosmosMongoFilter, sqlFilter } from '../constants'; -import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; -import { ext } from '../extensionVariables'; -import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { getRootPath } from '../utils/workspacUtils'; - -export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); - ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents..." - }, - async (progress) => { - uris = nonNullValue(uris, 'uris'); - collectionNode = nonNullValue(collectionNode, 'collectionNode'); - - progress.report({ increment: 20, message: "Parsing documents for errors" }); - const documents = await parseDocuments(uris); - progress.report({ increment: 30, message: "Parsed documents. Importing" }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo(collectionNode, documents); - } else { - result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); - - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); -} - -async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"] - } - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); - erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); - ext.outputChannel.show(); - throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); - } - for (const document of documents) { - const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; -} diff --git a/src/constants.ts b/src/constants.ts deleted file mode 100644 index 0e6a4a14e..000000000 --- a/src/constants.ts +++ /dev/null @@ -1,136 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export const isWindows: boolean = /^win/.test(process.platform); - -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; -import { ext } from './extensionVariables'; - -export namespace Links { - export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; -} - -export interface IThemedIconPath { - light: string; - dark: string; -} - -export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'light', iconName), - dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) - }; - assert(fs.existsSync(a.light)); - return a; -} - -export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), - dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) - }; - assert(fs.existsSync(a.light)); - return a; -} - -export function getResourcesPath(): string { - return ext.context.asAbsolutePath('resources'); -} - -export const doubleClickDebounceDelay = 500; //milliseconds - -export const defaultStoredProcedure = - `function sample(prefix) { - var collection = getContext().getCollection(); - - // Query documents and take 1st item. - var isAccepted = collection.queryDocuments( - collection.getSelfLink(), - 'SELECT * FROM root r', - function (err, feed, options) { - if (err) throw err; - - // Check the feed and if empty, set the body to 'no docs found', - // else take 1st element from feed - if (!feed || !feed.length) { - var response = getContext().getResponse(); - response.setBody('no docs found'); - } - - else { - var response = getContext().getResponse(); - var body = { prefix: prefix, feed: feed[0] }; - response.setBody(JSON.stringify(body)); - } - }); - - if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};` ; - -export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; - -// https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = 'test'; - -export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; -export const postgresLanguageId: string = 'postgres'; -export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = 'query'; -export const postgresDefaultPort = '5432'; -export const postgresDefaultDatabase = 'postgres'; -export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; - -export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; - -export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; - -export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag - } -}; - -export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; - -export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag - } -}; - -export const tableDefaultExperienceTag = 'Azure Table'; - -export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag - } -}; - -export const sqlDefaultExperienceTag = 'Core (SQL)'; - -export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag - } -}; - -export const postgresFlexibleFilter = { - type: 'Microsoft.DBforPostgreSQL/flexibleServers' -}; - -export const postgresSingleFilter = { - type: 'Microsoft.DBForPostgreSQL/servers' -}; diff --git a/src/docdb/docDBConnectionStrings.ts b/src/docdb/docDBConnectionStrings.ts deleted file mode 100644 index 946490d21..000000000 --- a/src/docdb/docDBConnectionStrings.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as url from 'url'; -import { ParsedConnectionString } from '../ParsedConnectionString'; -import { nonNullProp } from '../utils/nonNull'; - -export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); - const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); - const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); - if (!endpoint || !masterKey) { - throw new Error('Invalid Document DB connection string.'); - } - return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); -} - -function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; -} - -export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - public readonly documentEndpoint: string; - public readonly masterKey: string; - - constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; - - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, 'hostname'); - this.port = nonNullProp(parsedEndpoint, 'port'); - } -} diff --git a/src/docdb/getCosmosClient.ts b/src/docdb/getCosmosClient.ts deleted file mode 100644 index 3b285fc9c..000000000 --- a/src/docdb/getCosmosClient.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient } from "@azure/cosmos"; -import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; -import * as https from "https"; -import * as vscode from 'vscode'; -import { ext } from "../extensionVariables"; - -export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { - - const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; - return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); - -} diff --git a/src/docdb/registerDocDBCommands.ts b/src/docdb/registerDocDBCommands.ts deleted file mode 100644 index 5eb7545e4..000000000 --- a/src/docdb/registerDocDBCommands.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { commands } from "vscode"; -import { doubleClickDebounceDelay, sqlFilter } from "../constants"; -import { ext } from "../extensionVariables"; -import { DocDBAccountTreeItem } from "./tree/DocDBAccountTreeItem"; -import { DocDBCollectionTreeItem } from "./tree/DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItem } from "./tree/DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./tree/DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./tree/DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; - -export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openDocument", documentNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); - } - const childNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - - } - await node.deleteTreeItem(context); - }); -} - -export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); - await databaseNode.createChild(context); -} - -export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.createChild(context); -} - -export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - sqlFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/docdb/tree/DocDBAccountTreeItem.ts b/src/docdb/tree/DocDBAccountTreeItem.ts deleted file mode 100644 index 0cee7ed06..000000000 --- a/src/docdb/tree/DocDBAccountTreeItem.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; - -export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; - - public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } -} diff --git a/src/docdb/tree/DocDBAccountTreeItemBase.ts b/src/docdb/tree/DocDBAccountTreeItemBase.ts deleted file mode 100644 index da9eec6b7..000000000 --- a/src/docdb/tree/DocDBAccountTreeItemBase.ts +++ /dev/null @@ -1,95 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { rejectOnTimeout } from '../../utils/timeout'; -import { getCosmosClient } from '../getCosmosClient'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class provides common logic for DocumentDB, Graph, and Table accounts - * (DocumentDB is the base type for all Cosmos DB accounts) - */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; - - - constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) - }; - - this.valuesToMask.push(id, endpoint, masterKey); - } - - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public get isServerless(): boolean { - return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; - - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.databases.readAll(feedOptions); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: 'Database Name', - validateInput: validateDatabaseName, - stepName: 'createDatabase' - }); - - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ id: databaseName }); - return this.initChild(nonNullProp(database, 'resource')); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } -} - -function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; -} diff --git a/src/docdb/tree/DocDBCollectionTreeItem.ts b/src/docdb/tree/DocDBCollectionTreeItem.ts deleted file mode 100644 index 987bbe3b4..000000000 --- a/src/docdb/tree/DocDBCollectionTreeItem.ts +++ /dev/null @@ -1,92 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * Represents a DocumentDB collection - */ -export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - } -} diff --git a/src/docdb/tree/DocDBDatabaseTreeItem.ts b/src/docdb/tree/DocDBDatabaseTreeItem.ts deleted file mode 100644 index ee8c23694..000000000 --- a/src/docdb/tree/DocDBDatabaseTreeItem.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; - -export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Collection'; - - public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } - - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } -} diff --git a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts b/src/docdb/tree/DocDBDatabaseTreeItemBase.ts deleted file mode 100644 index aa7e8d779..000000000 --- a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ /dev/null @@ -1,161 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -const minThroughputFixed: number = 400; -const minThroughputPartitioned: number = 400; -const maxThroughput: number = 100000; -const throughputStepSize = 100; - -/** - * This class provides common logic for DocumentDB, Graph, and Table databases - * (DocumentDB is the base type for all Cosmos DB accounts) - */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public get id(): string { - return nonNullProp(this._database, 'id'); - } - - public get label(): string { - return nonNullProp(this._database, 'id'); - } - - public get link(): string { - return nonNullProp(this._database, '_self'); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.database(this._database.id).containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl(context: ICreateChildImplContext): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}` - }); - - const containerDefinition: ContainerDefinition = { - id: containerName - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey] - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !(containerDefinition.partitionKey); - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const throughput: number = Number(await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: 'throughputCapacity', - validateInput: (input: string) => validateThroughput(isFixed, input) - })); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, 'resource')); - } - - protected async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address/zipCode' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } -} - -function validateThroughput(isFixed: boolean, input: string): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const value = Number(input); - if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; -} - -function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; -} diff --git a/src/docdb/tree/DocDBDocumentTreeItem.ts b/src/docdb/tree/DocDBDocumentTreeItem.ts deleted file mode 100644 index 1505572d9..000000000 --- a/src/docdb/tree/DocDBDocumentTreeItem.ts +++ /dev/null @@ -1,133 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { sanitizeId } from './DocDBUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; - -/** - * Represents a Cosmos DB DocumentDB (SQL) document - */ -export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openDocument'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error(`The "_self" and "_etag" fields are required to update a document`); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; - const response = await this.getDocumentClient(client).replace(newData, options); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split('/'); - if (fields[0] === '') { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { //Partition Key exists, but this document doesn't have a value - return ''; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); - } -} diff --git a/src/docdb/tree/DocDBDocumentsTreeItem.ts b/src/docdb/tree/DocDBDocumentsTreeItem.ts deleted file mode 100644 index b8265444d..000000000 --- a/src/docdb/tree/DocDBDocumentsTreeItem.ts +++ /dev/null @@ -1,129 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; -import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class provides logic for DocumentDB collections - */ -export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = (await this.promptForPartitionKey(context, body)); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); - return nonNullProp(item, 'resource'); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split('/'); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { - const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: 'valueforParititionKey' - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { - //remove leading slash - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split('/'); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } -} diff --git a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts b/src/docdb/tree/DocDBStoredProcedureTreeItem.ts deleted file mode 100644 index 899eccd27..000000000 --- a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from "vscode"; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * Represents a Cosmos DB DocumentDB (SQL) stored procedure - */ -export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); - - constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openStoredProcedure'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get filePath(): string { - return this.label + '-cosmos-stored-procedure.js'; - } - - public get id(): string { - return this.procedure.id; - } - - public get label(): string { - return this.procedure.id; - } - - public get link(): string { - return this.procedure._self; - } - - public async getFileContent(): Promise { - return typeof this.procedure.body === 'string' ? this.procedure.body : ''; - - } - - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, 'resource'); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); - } -} diff --git a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts b/src/docdb/tree/DocDBStoredProceduresTreeItem.ts deleted file mode 100644 index 4c3ddfd1a..000000000 --- a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from "vscode"; -import { defaultStoredProcedure } from '../../constants'; -import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class represents the DocumentDB "Stored Procedures" node in the tree - */ -export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = (await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: 'createStoredProcedure', - validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) - })).trim(); - const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; - context.showCreatingTreeItem(spID); - const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, 'resource')); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize("nameLength", "Name has to be between 1 and 255 chars long"); - } - - if (/[/\\?#&]/.test(name)) { - return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); - } - - return undefined; - } -} diff --git a/src/docdb/tree/DocDBTreeItemBase.ts b/src/docdb/tree/DocDBTreeItemBase.ts deleted file mode 100644 index 4424603ae..000000000 --- a/src/docdb/tree/DocDBTreeItemBase.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * This class provides common iteration logic for DocumentDB accounts, databases, and collections - */ -export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; - - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public root: IDocDBTreeRoot; - - public abstract initChild(resource: T): AzExtTreeItem; - - public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); - } - - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); - - this._batchSize *= 2; - - return resourceArray.map((resource: T) => this.initChild(resource)); - } -} diff --git a/src/docdb/tree/DocDBUtils.ts b/src/docdb/tree/DocDBUtils.ts deleted file mode 100644 index 3d45cf950..000000000 --- a/src/docdb/tree/DocDBUtils.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/** - * Sanitize an the id of a DocDB tree item so it can be safely used in a query string. - * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding - */ -export function sanitizeId(id: string): string { - return id.replace(/\+/g, ' '); -} diff --git a/src/docdb/tree/IDocDBTreeRoot.ts b/src/docdb/tree/IDocDBTreeRoot.ts deleted file mode 100644 index 9179eb454..000000000 --- a/src/docdb/tree/IDocDBTreeRoot.ts +++ /dev/null @@ -1,14 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient } from "@azure/cosmos"; - -export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; -} diff --git a/src/extension.ts b/src/extension.ts deleted file mode 100644 index e68744157..000000000 --- a/src/extension.ts +++ /dev/null @@ -1,215 +0,0 @@ -/*-------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; -import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; -import { platform } from 'os'; -import * as vscode from 'vscode'; -import { DatabasesFileSystem } from './DatabasesFileSystem'; -import { findTreeItem } from './commands/api/findTreeItem'; -import { pickTreeItem } from './commands/api/pickTreeItem'; -import { revealTreeItem } from './commands/api/revealTreeItem'; -import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { importDocuments } from './commands/importDocuments'; -import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; -import { registerDocDBCommands } from './docdb/registerDocDBCommands'; -import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; -import { ext } from './extensionVariables'; -import { getResourceGroupsApi } from './getExtensionApi'; -import { registerGraphCommands } from './graph/registerGraphCommands'; -import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; -import { registerMongoCommands } from './mongo/registerMongoCommands'; -import { setConnectedNode } from './mongo/setConnectedNode'; -import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; -import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; -import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; -import { DatabaseResolver } from './resolver/AppResolver'; -import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; -import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; -import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; -import { localize } from './utils/localize'; - -const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; - -export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = 'true'; - activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); - - const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); - ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { - if (platform() !== 'win32') { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); - } - - await ext.attachedAccountsNode.attachEmulator(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh(actionContext, node); - } - }); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { - const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); - if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { - const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); - } - if (node instanceof MongoAccountTreeItem) { - if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments(actionContext, uris || [selectedNode], undefined); - } else { - await importDocuments(actionContext, undefined, selectedNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { - if (!node) { - node = await ext.rgApi.pickAppResource(actionContext, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); - registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); - registerEvent( - 'cosmosDB.onDidChangeConfiguration', - vscode.workspace.onDidChangeConfiguration, - async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { - actionContext.telemetry.properties.isActivationEvent = "true"; - actionContext.errorHandling.suppressDisplay = true; - if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { - await vscode.commands.executeCommand("azureDatabases.refresh"); - } - }); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); - registerReportIssueCommand('azureDatabases.reportIssue'); - }); - - return createApiProvider([{ - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: '1.2.0' - }]); -} - -// this method is called when your extension is deactivated -export function deactivateInternal(): void { - // NOOP -} - -export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { - if (!node) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); - } - - await SubscriptionTreeItem.createChild(context, node); -} - -export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await deleteDatabaseAccount(context, node, false) -} - -export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { - const message = 'The connection string has been copied to the clipboard'; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); -} diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts deleted file mode 100644 index 4a3fc2650..000000000 --- a/src/extensionVariables.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; -import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; -import { ExtensionContext, SecretStorage, TreeView } from "vscode"; -import { DatabasesFileSystem } from "./DatabasesFileSystem"; -import { MongoDBLanguageClient } from "./mongo/languageClient"; -import { MongoCodeLensProvider } from "./mongo/services/MongoCodeLensProvider"; -import { MongoDatabaseTreeItem } from "./mongo/tree/MongoDatabaseTreeItem"; -import { PostgresCodeLensProvider } from "./postgres/services/PostgresCodeLensProvider"; -import { PostgresDatabaseTreeItem } from "./postgres/tree/PostgresDatabaseTreeItem"; -import { AttachedAccountsTreeItem } from "./tree/AttachedAccountsTreeItem"; -import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWithAttached"; - -/** - * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts - */ -export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = 'azureDatabases'; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; - - export namespace settingsKeys { - export const mongoShellPath = 'mongo.shell.path'; - export const mongoShellArgs = 'mongo.shell.args'; - export const documentLabelFields = 'cosmosDB.documentLabelFields'; - export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; - export const mongoShellTimeout = 'mongo.shell.timeout'; - export const batchSize = 'azureDatabases.batchSize'; - - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } -} diff --git a/src/getExtensionApi.ts b/src/getExtensionApi.ts deleted file mode 100644 index bfd553e74..000000000 --- a/src/getExtensionApi.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { apiUtils } from "@microsoft/vscode-azext-utils"; -import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; -import { Extension, extensions } from "vscode"; -import { localize } from "./utils/localize"; - -export async function getApiExport(extensionId: string): Promise { - const extension: Extension | undefined = extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } - - return extension.exports; - } - - return undefined; -} - -export async function getResourceGroupsApi(): Promise { - const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); - if (rgApiProvider) { - return rgApiProvider.getApi('0.0.1'); - } else { - throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); - } -} diff --git a/src/graph/gremlinEndpoints.ts b/src/graph/gremlinEndpoints.ts deleted file mode 100644 index 1ef6b283d..000000000 --- a/src/graph/gremlinEndpoints.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { nonNullValue } from '../utils/nonNull'; -import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; - -export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; -} - -export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - - const documentSuffix = '.documents.azure.com'; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); - - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); - - return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } -} - -/** - * Parses a IGremlinPoint from a URL - * @param url An account URL such as 'https://.documents.azure.com:443/' - */ -function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; -} diff --git a/src/graph/registerGraphCommands.ts b/src/graph/registerGraphCommands.ts deleted file mode 100644 index 1746c638b..000000000 --- a/src/graph/registerGraphCommands.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; -import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; -import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./tree/GraphTreeItem"; - -export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph(context, GraphTreeItem.contextValue); - } - await node.showExplorer(context); - }, doubleClickDebounceDelay); -} - -export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); -} - -export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.createChild(context); -} - -async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosGremlinFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/graph/tree/GraphAccountTreeItem.ts b/src/graph/tree/GraphAccountTreeItem.ts deleted file mode 100644 index 7e1f561fa..000000000 --- a/src/graph/tree/GraphAccountTreeItem.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; - -export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } - - public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } -} diff --git a/src/graph/tree/GraphCollectionTreeItem.ts b/src/graph/tree/GraphCollectionTreeItem.ts deleted file mode 100644 index 63709d977..000000000 --- a/src/graph/tree/GraphCollectionTreeItem.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; - -export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - - } -} diff --git a/src/graph/tree/GraphDatabaseTreeItem.ts b/src/graph/tree/GraphDatabaseTreeItem.ts deleted file mode 100644 index 1c5332700..000000000 --- a/src/graph/tree/GraphDatabaseTreeItem.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; -import { GraphAccountTreeItem } from './GraphAccountTreeItem'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; - -export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Graph'; - - constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { - super(parent, database); - } - - public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } - - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } - - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } - - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - - } - - protected override async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } -} diff --git a/src/graph/tree/GraphTreeItem.ts b/src/graph/tree/GraphTreeItem.ts deleted file mode 100644 index 800fded5a..000000000 --- a/src/graph/tree/GraphTreeItem.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; - -const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; - -export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this.commandId = 'cosmosDB.openGraphExplorer'; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } -} diff --git a/src/mongo/MongoCommand.ts b/src/mongo/MongoCommand.ts deleted file mode 100644 index 79c33731f..000000000 --- a/src/mongo/MongoCommand.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { RecognitionException } from 'antlr4ts'; -import * as vscode from 'vscode'; - -export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; -} - -export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; -} diff --git a/src/mongo/MongoScrapbook.ts b/src/mongo/MongoScrapbook.ts deleted file mode 100644 index d5dfe6d00..000000000 --- a/src/mongo/MongoScrapbook.ts +++ /dev/null @@ -1,491 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ObjectID } from 'bson'; -import { Collection } from 'mongodb'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { filterType, findType } from '../utils/array'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { mongoLexer } from './grammar/mongoLexer'; -import * as mongoParser from './grammar/mongoParser'; -import { MongoVisitor } from './grammar/visitors'; -import { ErrorDescription, MongoCommand } from './MongoCommand'; -import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; -import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of (command.errors || [])) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; -} - -export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); -} - -export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); - return await executeCommand(context, command); -} - -function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } -} - -export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { - return getAllCommandsFromText(document.getText()); -} - -async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { - const label: string = 'Scrapbook-execute-all-results'; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } -} - -async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === 'find' && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, 'collection'); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); - await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === 'findOne') { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp(command, 'collection'); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); - if (!colNode) { - throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = 'Scrapbook-results'; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error('No MongoDB command found at the current cursor location.'); - } -} - -async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { - if (command.name === 'drop') { - await database.refresh(context); - } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); - if (collectionNode) { - await collectionNode.refresh(context); - } - } -} - -export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "" - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; -} - -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; -} - -class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop'); - this.commands.push({ - range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); - return {}; - } - } - - private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' - this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); - if (argumentContextArray.length > 1) { - this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); - return {}; - } - } - - private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { - if (!tokenText) { // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop'); - const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* - We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. - $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. - {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). - We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those - What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. - */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } - -} diff --git a/src/mongo/MongoShell.ts b/src/mongo/MongoShell.ts deleted file mode 100644 index b8f982ee8..000000000 --- a/src/mongo/MongoShell.ts +++ /dev/null @@ -1,187 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; -import { randomUtils } from '../utils/randomUtils'; -import { getBatchSizeSetting } from '../utils/workspacUtils'; -import { wrapError } from '../utils/wrapError'; - -const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; - -const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = '(More)'; - -const sentinelBase = 'EXECUTION COMPLETED'; -const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } - -export class MongoShell extends vscode.Disposable { - - constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { - super(() => this.dispose()); - } - - public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '' - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut(text => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); - - resolve(stdOutNoSentinel); - } - })); - disposables.push( - this._process.onStdErr(text => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - })); - disposables.push( - this._process.onError(error => { - reject(error); - })); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error("The process exited prematurely."); - } - - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } - finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } -} - -function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout( - () => { - reject(timeoutMessage); - }, - timeoutSeconds * 1000); - } -} - -function convertToSingleLine(script: string): string { - return script.split(os.EOL) - .map(line => line.trim()) - .join(''); - -} - -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} - -function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); -} diff --git a/src/mongo/connectToMongoClient.ts b/src/mongo/connectToMongoClient.ts deleted file mode 100644 index 88aa2df17..000000000 --- a/src/mongo/connectToMongoClient.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { MongoClient, MongoClientOptions } from 'mongodb'; -import { emulatorPassword, Links } from '../constants'; - -export async function connectToMongoClient(connectionString: string, appName: string): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string, name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - throw error; - } -} - -export class MongoConnectError extends Error { - constructor() { - super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); - } -} - -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); -} diff --git a/src/mongo/errorListeners.ts b/src/mongo/errorListeners.ts deleted file mode 100644 index ea582d544..000000000 --- a/src/mongo/errorListeners.ts +++ /dev/null @@ -1,67 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { Recognizer } from 'antlr4ts/Recognizer'; -import { Token } from 'antlr4ts/Token'; -import * as vscode from "vscode"; -import { ErrorDescription } from './MongoCommand'; - -export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { - - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } -} - -export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { - - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } -} diff --git a/src/mongo/grammar/mongo.tokens b/src/mongo/grammar/mongo.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/mongo/grammar/mongo.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/mongo/grammar/mongoLexer.tokens b/src/mongo/grammar/mongoLexer.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/mongo/grammar/mongoLexer.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/mongo/grammar/mongoLexer.ts b/src/mongo/grammar/mongoLexer.ts deleted file mode 100644 index 3b6cbbdd0..000000000 --- a/src/mongo/grammar/mongoLexer.ts +++ /dev/null @@ -1,247 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { RuleContext } from 'antlr4ts/RuleContext'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; - - - -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = [ - "DEFAULT_MODE" - ]; - - public static readonly ruleNames: string[] = [ - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", - "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", - "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", - "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", - "ExponentPart", "DecimalDigit", "WHITESPACE" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoLexer.ruleNames; } - - @Override - public get serializedATN(): string { return mongoLexer._serializedATN; } - - @Override - public get modeNames(): string[] { return mongoLexer.modeNames; } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text) - ; - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } - -} - diff --git a/src/mongo/grammar/mongoListener.ts b/src/mongo/grammar/mongoListener.ts deleted file mode 100644 index 43514f500..000000000 --- a/src/mongo/grammar/mongoListener.ts +++ /dev/null @@ -1,208 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - - -import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - - -/** - * This interface defines a complete listener for a parse tree produced by - * `mongoParser`. - */ -export interface mongoListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - enterMongoCommands?: (ctx: MongoCommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - exitMongoCommands?: (ctx: MongoCommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - enterCommands?: (ctx: CommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - exitCommands?: (ctx: CommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - enterCommand?: (ctx: CommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - exitCommand?: (ctx: CommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - enterEmptyCommand?: (ctx: EmptyCommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - exitEmptyCommand?: (ctx: EmptyCommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - enterCollection?: (ctx: CollectionContext) => void; - /** - * Exit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - exitCollection?: (ctx: CollectionContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - enterFunctionCall?: (ctx: FunctionCallContext) => void; - /** - * Exit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - exitFunctionCall?: (ctx: FunctionCallContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - enterArguments?: (ctx: ArgumentsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - exitArguments?: (ctx: ArgumentsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - enterArgument?: (ctx: ArgumentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - exitArgument?: (ctx: ArgumentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - enterObjectLiteral?: (ctx: ObjectLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - exitObjectLiteral?: (ctx: ObjectLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - enterArrayLiteral?: (ctx: ArrayLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - exitArrayLiteral?: (ctx: ArrayLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - enterElementList?: (ctx: ElementListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - exitElementList?: (ctx: ElementListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - enterPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - exitPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - enterPropertyValue?: (ctx: PropertyValueContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - exitPropertyValue?: (ctx: PropertyValueContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - enterLiteral?: (ctx: LiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - exitLiteral?: (ctx: LiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - enterPropertyName?: (ctx: PropertyNameContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - exitPropertyName?: (ctx: PropertyNameContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - enterComment?: (ctx: CommentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - exitComment?: (ctx: CommentContext) => void; -} - diff --git a/src/mongo/grammar/mongoParser.ts b/src/mongo/grammar/mongoParser.ts deleted file mode 100644 index c1d38f4d0..000000000 --- a/src/mongo/grammar/mongoParser.ts +++ /dev/null @@ -1,1466 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { TokenStream } from 'antlr4ts/TokenStream'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { mongoListener } from './mongoListener'; -import { mongoVisitor } from './mongoVisitor'; - - - - -export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", "commands", "command", "emptyCommand", "collection", - "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", - "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", - "literal", "propertyName", "comment" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoParser.ruleNames; } - - @Override - public get serializedATN(): string { return mongoParser._serializedATN; } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + - "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } - -} - -export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } -} - - -export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } -} - - -export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_command; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } -} - - -export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } -} - - -export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } -} - - -export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } -} - - -export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } -} - - -export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } -} - - -export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } -} - - -export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } - public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } - public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } -} - - -export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } - public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } -} - - diff --git a/src/mongo/grammar/mongoVisitor.ts b/src/mongo/grammar/mongoVisitor.ts deleted file mode 100644 index eb001a6e9..000000000 --- a/src/mongo/grammar/mongoVisitor.ts +++ /dev/null @@ -1,143 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - - -import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by `mongoParser`. - * - * @param The return type of the visit operation. Use `void` for - * operations with no return type. - */ -export interface mongoVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitMongoCommands?: (ctx: MongoCommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommands?: (ctx: CommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommand?: (ctx: CommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - * @return the visitor result - */ - visitEmptyCommand?: (ctx: EmptyCommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCollection?: (ctx: CollectionContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFunctionCall?: (ctx: FunctionCallContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArguments?: (ctx: ArgumentsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArgument?: (ctx: ArgumentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitObjectLiteral?: (ctx: ObjectLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArrayLiteral?: (ctx: ArrayLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitElementList?: (ctx: ElementListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyAssignment?: (ctx: PropertyAssignmentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyValue?: (ctx: PropertyValueContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - * @return the visitor result - */ - visitLiteral?: (ctx: LiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyName?: (ctx: PropertyNameContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitComment?: (ctx: CommentContext) => Result; -} - diff --git a/src/mongo/grammar/visitors.ts b/src/mongo/grammar/visitors.ts deleted file mode 100644 index e1ba1b63d..000000000 --- a/src/mongo/grammar/visitors.ts +++ /dev/null @@ -1,83 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; -import { mongoVisitor } from './mongoVisitor'; - -export class MongoVisitor implements mongoVisitor { - - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return null; - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } -} diff --git a/src/mongo/languageClient.ts b/src/mongo/languageClient.ts deleted file mode 100644 index e4bd4aefd..000000000 --- a/src/mongo/languageClient.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -import * as nls from 'vscode-nls'; -import { ext } from '../extensionVariables'; -import { IConnectionParams } from './services/IConnectionParams'; - -const localize = nls.loadMessageBundle(); - -export class MongoDBLanguageClient { - - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle ? - ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : - ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'mongo', scheme: 'file' }, - { language: 'mongo', scheme: 'untitled' } - ] - }; - - // Create the language client and start the client. - this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect(connectionString: string, databaseName: string): Promise { - await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } -} diff --git a/src/mongo/languageServer.ts b/src/mongo/languageServer.ts deleted file mode 100644 index d5d6ec484..000000000 --- a/src/mongo/languageServer.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from 'vscode-languageserver'; -import { LanguageService } from './services/languageService'; - -// -// -// -// HOW TO DEBUG THE LANGUAGE SERVER -// -// -// 1. Start the extension via F5 -// 2. Under vscode Debug pane, switch to "Attach to Language Server" -// 3. F5 -// -// -// - -// Create a connection for the server -const connection: IConnection = createConnection(); -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -console.log = connection.console.log.bind(connection.console); -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -console.error = connection.console.error.bind(connection.console); - -new LanguageService(connection); - -// Listen on the connection -connection.listen(); diff --git a/src/mongo/mongoConnectionStrings.ts b/src/mongo/mongoConnectionStrings.ts deleted file mode 100644 index 5f73db484..000000000 --- a/src/mongo/mongoConnectionStrings.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import { testDb } from "../constants"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullValue } from "../utils/nonNull"; -import { connectToMongoClient } from "./connectToMongoClient"; - -// Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): -// mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] -// Some example connection strings: -// mongodb://dbuser:dbpassword@dbname.mlab.com:14118 -// mongodb+srv://db1.example.net:27017,db2.example.net:2500/?replicaSet=test -// mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/database?ssh=true -// Regex splits into three parts: -// Full match -// mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] -// [database] - -const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; -const parseDatabaseName = '\/?([^/?]+)?'; -const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); - -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } - - return undefined; -} - -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } -} - -export async function parseMongoConnectionString(connectionString: string): Promise { - - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; - - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - - return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); -} - -export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } -} - -/** - * Encodes the username and password in the given Mongo DB connection string. - */ -export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } - - return connectionString; -} diff --git a/src/mongo/registerMongoCommands.ts b/src/mongo/registerMongoCommands.ts deleted file mode 100644 index 2dc36477a..000000000 --- a/src/mongo/registerMongoCommands.ts +++ /dev/null @@ -1,223 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { Experience, MongoExperience } from '../AzureDBExperiences'; -import { cosmosMongoFilter } from "../constants"; -import { ext } from "../extensionVariables"; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { MongoConnectError } from './connectToMongoClient'; -import { MongoDBLanguageClient } from "./languageClient"; -import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; -import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; -import { setConnectedNode } from "./setConnectedNode"; -import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; -import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; - -const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; -let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = 'mongo'; - -export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); - } - - const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); - if (oldNode) { - await oldNode.refresh(context); - } - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); - registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - }); -} - -async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); -} - -function launchMongoShell(): void { - const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); - terminal.sendText(`mongo`); - terminal.show(); -} - -function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }); - - // Update errors when document opened/changed - registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); -} - -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } -} - -export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); - - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); -} - -export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); -} - -export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } -} - -export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/mongo/services/IConnectionParams.ts b/src/mongo/services/IConnectionParams.ts deleted file mode 100644 index eec39e4cf..000000000 --- a/src/mongo/services/IConnectionParams.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; -} diff --git a/src/mongo/services/MongoCodeLensProvider.ts b/src/mongo/services/MongoCodeLensProvider.ts deleted file mode 100644 index 3407c50dd..000000000 --- a/src/mongo/services/MongoCodeLensProvider.ts +++ /dev/null @@ -1,75 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; - -export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; - - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } - - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } - - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; - - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; - - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized ? - 'Initializing...' : - isConnected ? - `Connected to ${database}` : - `Connect to a database`, - command: isInitialized && 'cosmosDB.connectMongoDB' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); - - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: 'cosmosDB.executeAllMongoCommands' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); - - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: 'cosmosDB.executeMongoCommand', - arguments: [cmd.range.start] - }, - range: cmd.range - }); - } - } - - return lenses; - }); - } -} diff --git a/src/mongo/services/completionItemProvider.ts b/src/mongo/services/completionItemProvider.ts deleted file mode 100644 index cba51890c..000000000 --- a/src/mongo/services/completionItemProvider.ts +++ /dev/null @@ -1,439 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-non-null-assertion */ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) - .then(list => { - return list!.items.map(item => { - const startPositionOffset = document.offsetAt(item.textEdit!.range.start); - const endPositionOffset = document.offsetAt(item.textEdit!.range.end); - item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range - }, - kind: CompletionItemKind.Keyword, - label: 'db' - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range) - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then(collections => { - return collections.map(collection => ({ - textEdit: { - newText: collection.collectionName, - range - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}` - })); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range) - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}` - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } - -} diff --git a/src/mongo/services/languageService.ts b/src/mongo/services/languageService.ts deleted file mode 100644 index 83b1b594e..000000000 --- a/src/mongo/services/languageService.ts +++ /dev/null @@ -1,90 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) - -import { Db } from 'mongodb'; -import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; -import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; - -export class LanguageService { - - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] } - } - }; - }); - - connection.onCompletion(textDocumentPosition => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) - .then(account => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db) - .then(schemas => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: uri => this.schemaService.resolveSchema(uri), - contributions: [] - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas - }); - } -} diff --git a/src/mongo/services/mongoScript.ts b/src/mongo/services/mongoScript.ts deleted file mode 100644 index 8d4c85398..000000000 --- a/src/mongo/services/mongoScript.ts +++ /dev/null @@ -1,101 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, Position } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { SchemaService } from './schemaService'; - -export class MongoScriptDocumentManager { - - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - } - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } -} - -export class MongoScriptDocument { - - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } - - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); - - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); - } - return Promise.resolve([]); - } -} - -class NodeFinder extends MongoVisitor { - - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; - const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; - const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; - const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; - - if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } -} diff --git a/src/mongo/services/schemaService.ts b/src/mongo/services/schemaService.ts deleted file mode 100644 index cf70e8cde..000000000 --- a/src/mongo/services/schemaService.ts +++ /dev/null @@ -1,628 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ - -import { Cursor, Db } from 'mongodb'; -import { SchemaConfiguration } from 'vscode-json-languageservice'; -// eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; - -export class SchemaService { - - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections() - .then(collections => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push(...[{ - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)] - }, { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)] - }]); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {} - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - for (const property of Object.keys(document)) { - if (!parent && - ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'] - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' - }, - $language: { - type: 'string', - description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' - }, - $caseSensitive: { - type: 'boolean', - description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` - } - }, - required: ['$search'] - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate' - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri - } - }; - schema.properties!.$and = { - type: 'array', - description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri - } - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri - } - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {} - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value' - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value' - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value' - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value' - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value' - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value' - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array' - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array' - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field' - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type' - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0] - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression' - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type' - }, - coordinates: { - type: 'array' - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string' - }, - properties: { - type: 'object' - } - } - } - } - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array' - }, - $polygon: { - type: 'array' - }, - $center: { - type: 'array' - }, - $centerSphere: { - type: 'array' - } - } - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema - } - }; - expressionSchema.properties.$near = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query' - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size' - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties } - }; - schema.properties!.$elemMatch = { - type: 'object' - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view' - } - } - - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri - } - } - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'] - } - }, - additionalProperties: { - type: 'object' - } - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' - } - } - }); - return { - type: 'object', - oneOf: schemas - }; - } - - private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then(hasNext => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then(doc => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } - -} diff --git a/src/mongo/setConnectedNode.ts b/src/mongo/setConnectedNode.ts deleted file mode 100644 index f5680d09d..000000000 --- a/src/mongo/setConnectedNode.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from "../extensionVariables"; -import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; - -export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); -} diff --git a/src/mongo/tree/IMongoTreeRoot.ts b/src/mongo/tree/IMongoTreeRoot.ts deleted file mode 100644 index d9b68980d..000000000 --- a/src/mongo/tree/IMongoTreeRoot.ts +++ /dev/null @@ -1,9 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface IMongoTreeRoot { - isEmulator: boolean | undefined; -} diff --git a/src/mongo/tree/MongoAccountTreeItem.ts b/src/mongo/tree/MongoAccountTreeItem.ts deleted file mode 100644 index baa870c23..000000000 --- a/src/mongo/tree/MongoAccountTreeItem.ts +++ /dev/null @@ -1,140 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; -import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; - -export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error('Missing connection string'); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); - - const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [{ - name: databaseInConnectionString, - empty: false - }]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); - databases = result.databases; - } - return databases - .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty - .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } - finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createMongoDatabase', - validateInput: validateDatabaseName - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } -} - -export function validateDatabaseName(database: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return "Database name cannot contain these characters - `/\\. \"$#?=`"; - } - return undefined; -} - -export interface IDatabaseInfo { - name?: string; - empty?: boolean; -} diff --git a/src/mongo/tree/MongoCollectionTreeItem.ts b/src/mongo/tree/MongoCollectionTreeItem.ts deleted file mode 100644 index eca0c8d32..000000000 --- a/src/mongo/tree/MongoCollectionTreeItem.ts +++ /dev/null @@ -1,320 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullValue } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { MongoCommand } from '../MongoCommand'; -import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; -type MongoDocument = { _id: string }; -class FunctionDescriptor { - public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { - } -} - -export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, '_id'), - upsert: false - } - }; - }); - - const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = await this.getCachedChildren(context); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(children.map(c => c.document), null, 2); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get filePath(): string { - return this.label + '-cosmos-collection.json'; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { - const documentNodes = await this.getCachedChildren(context); - for (const doc of docs) { - const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection.find(this._query).batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - 'invalidMongoDocument', - doc => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; - - const functions = { - drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), - count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), - findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), - insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), - insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), - insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), - deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), - deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), - remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error(`Too few arguments passed to command ${command.name}.`); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error(`Too many arguments passed to command ${command.name}`); - } - if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number, name?: string } = e; - const NamespaceNotFoundCode = 26; - if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne(query?: Object, fieldsOption?: Object): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, '\t'); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error("The insert command requires at least one argument"); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count(query?: Object[], options?: MongoCountPreferences): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, '\t'); - } -} - -function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title - }, - (_progress) => { - return promise; - }); -} - -function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } -} diff --git a/src/mongo/tree/MongoDatabaseTreeItem.ts b/src/mongo/tree/MongoDatabaseTreeItem.ts deleted file mode 100644 index 73a7c6a22..000000000 --- a/src/mongo/tree/MongoDatabaseTreeItem.ts +++ /dev/null @@ -1,258 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import { Collection, Db, DbCollectionOptions } from 'mongodb'; -import * as path from 'path'; -import * as process from 'process'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { MongoCommand } from '../MongoCommand'; -import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; -import { MongoShell } from '../MongoShell'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoAccountTreeItem } from './MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; -const executingInShellMsg = "Executing command in Mongo shell"; - -export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map(collection => new MongoCollectionTreeItem(this, collection)); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: 'createMongoCollection', - validateInput: validateMongoCollectionName - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); - return accountConnection.db(this.databaseName); - } - - public async executeCommand(command: MongoCommand, context: IActionContext): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); - const result = await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - - } - - if (command.name === 'createCollection') { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); - } else { - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - } - } - - public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection(collectionName, options); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); - - if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); - return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); - } - - private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongo', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongo'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; - const browse: vscode.MessageItem = { title: 'Open installation page' }; - const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; - const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; - const tryAgain: vscode.MessageItem = { title: 'Try again' }; - const response2 = await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } -} - -export function validateMongoCollectionName(collectionName: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; -} - -function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title - }, - (_progress) => { - return promise; - }); -} - -export function stripQuotes(term: string): string { - if ((term.startsWith('\'') && term.endsWith('\'')) - || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; -} diff --git a/src/mongo/tree/MongoDocumentTreeItem.ts b/src/mongo/tree/MongoDocumentTreeItem.ts deleted file mode 100644 index ad44e43c3..000000000 --- a/src/mongo/tree/MongoDocumentTreeItem.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -export interface IMongoDocument { - _id: string | ObjectID; - - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; -} - -export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private _label: string; - - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = 'cosmosDB.openDocument'; - ext.fileSystem.fireChangedEvent(this); - } - - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } - - public get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public static async update(collection: Collection, newDocument: IMongoDocument): Promise { - if (!newDocument._id) { - throw new Error(`The "_id" field is required to update a document.`); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); - if (result.modifiedCount !== 1) { - throw new Error(`Failed to update document with _id '${newDocument._id}'.`); - } - return newDocument; - } - - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); - const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error(`Failed to delete document with _id '${this.document._id}'.`); - } - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); - } -} diff --git a/src/postgres/abstract/AbstractPostgresClient.ts b/src/postgres/abstract/AbstractPostgresClient.ts deleted file mode 100644 index c1fa29c4f..000000000 --- a/src/postgres/abstract/AbstractPostgresClient.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; -import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; -import { PostgresServerType } from "./models"; - -export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; - -export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context) - case PostgresServerType.Single: - return await createPostgreSQLClient(context) - default: - throw new Error("Service not implemented."); - } -} diff --git a/src/postgres/abstract/models.ts b/src/postgres/abstract/models.ts deleted file mode 100644 index 6bdadf16a..000000000 --- a/src/postgres/abstract/models.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; - -export enum PostgresServerType { - Flexible = 'Flexible', - Single = 'Single' -} - -export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } - -export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; - -/** - * Billing information related properties of a server. - */ -export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; -} - -export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; -} - -export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; - -export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; diff --git a/src/postgres/commands/checkAuthentication.ts b/src/postgres/commands/checkAuthentication.ts deleted file mode 100644 index 6799d060c..000000000 --- a/src/postgres/commands/checkAuthentication.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { invalidCredentialsErrorType } from "../postgresConstants"; -import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { configurePostgresFirewall } from "./configurePostgresFirewall"; -import { enterPostgresCredentials } from "./enterPostgresCredentials"; - -export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); - - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; -} diff --git a/src/postgres/commands/configurePostgresFirewall.ts b/src/postgres/commands/configurePostgresFirewall.ts deleted file mode 100644 index 52a378fca..000000000 --- a/src/postgres/commands/configurePostgresFirewall.ts +++ /dev/null @@ -1,69 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { getPublicIpv4 } from "../../utils/getIp"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; - -export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), - { - modal: true, - stepName: 'postgresAddFirewallRule' - }, - { title: DialogResponses.yes.title } - ); - - await setFirewallRule(context, treeItem, ip); -} - -export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { - - const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); - const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); - const serverName: string = nonNullProp(treeItem, 'azureName'); - - const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip - }; - - const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); - }); - const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); -} - -export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); -} diff --git a/src/postgres/commands/connectPostgresDatabase.ts b/src/postgres/commands/connectPostgresDatabase.ts deleted file mode 100644 index 6996f7d03..000000000 --- a/src/postgres/commands/connectPostgresDatabase.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from 'vscode'; -import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from "../../extensionVariables"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; - -export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); - - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } -} diff --git a/src/postgres/commands/copyConnectionString.ts b/src/postgres/commands/copyConnectionString.ts deleted file mode 100644 index 716bbd5b6..000000000 --- a/src/postgres/commands/copyConnectionString.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; - -export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); - } else { - connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); - } - - await vscode.env.clipboard.writeText(connectionString); - const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); - void vscode.window.showInformationMessage(message); -} diff --git a/src/postgres/commands/createPostgresDatabase.ts b/src/postgres/commands/createPostgresDatabase.ts deleted file mode 100644 index 6c096a52b..000000000 --- a/src/postgres/commands/createPostgresDatabase.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -import { connectPostgresDatabase } from './connectPostgresDatabase'; - -export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); -} diff --git a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts deleted file mode 100644 index 81d54b9af..000000000 --- a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ /dev/null @@ -1,12 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; - -export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; -} diff --git a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts deleted file mode 100644 index 27b32993c..000000000 --- a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; - -export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { - returnType?: string; -} diff --git a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts deleted file mode 100644 index 8c4df098b..000000000 --- a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, IActionContext } from "@microsoft/vscode-azext-utils"; -import { PostgresFunctionsTreeItem } from "../../../tree/PostgresFunctionsTreeItem"; -import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; -import { IPostgresFunctionQueryWizardContext } from "./IPostgresFunctionQueryWizardContext"; -import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; -import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; -import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; - -export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], - executeSteps: [new FunctionQueryCreateStep()], - title: 'Create PostgreSQL Function Query' - }); - - await runPostgresQueryWizard(wizard, wizardContext, treeItem); -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts deleted file mode 100644 index 9356882d9..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "../../../../../utils/nonNull"; -import { wrapArgInQuotes } from "../../../../runPostgresQuery"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IPostgresFunctionQueryWizardContext): Promise { - context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); - } - - public shouldExecute(): boolean { - return true; - } -} - -const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) - RETURNS ${returnType} - LANGUAGE plpgsql -AS $function$ - BEGIN - /* function body */ - END; -$function$ -`; diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts deleted file mode 100644 index cfacc0f64..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts deleted file mode 100644 index 36d798074..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { validateIdentifier } from "../../validateIdentifier"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideFunctionName', 'Provide function name'), - validateInput: validateIdentifier - })).trim(); - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts deleted file mode 100644 index 63f703793..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ /dev/null @@ -1,50 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; -import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; - -export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); - returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); - - context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize('selectReturnType', 'Select return type') - })).data; - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } - - public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { - return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } -} - -// A subset of return types available on pgAdmin -const returnTypes: string[] = [ - 'bigint', - 'bigint[]', - 'boolean', - 'boolean[]', - 'character', - 'character[]', - 'date', - 'date[]', - 'integer', - 'integer[]', - 'json', - 'json[]', - 'oid', - 'oid[]', - 'smallint', - 'smallint[]', - 'text', - 'void' -]; diff --git a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts deleted file mode 100644 index 925695e56..000000000 --- a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; -import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from '../../../utils/vscodeUtils'; -import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; -import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; -import { connectPostgresDatabase } from "../connectPostgresDatabase"; -import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; - -export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); - - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } -} diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts deleted file mode 100644 index f1ddbe51b..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, IActionContext } from "@microsoft/vscode-azext-utils"; -import { PostgresStoredProceduresTreeItem } from "../../../tree/PostgresStoredProceduresTreeItem"; -import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; -import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; -import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; - -export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: 'Create PostgreSQL Stored Procedure Query' - }); - - await runPostgresQueryWizard(wizard, context, treeItem); -} diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts deleted file mode 100644 index 2cf3ef916..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "../../../../../utils/nonNull"; -import { wrapArgInQuotes } from "../../../../runPostgresQuery"; -import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; - -export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); - } - - public shouldExecute(): boolean { - return true; - } -} - -const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) - LANGUAGE plpgsql -AS $$ - BEGIN - /* stored procedure body */ - END; -$$ -`; diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts deleted file mode 100644 index bf9a00392..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; -import { validateIdentifier } from "../../validateIdentifier"; - -export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), - validateInput: validateIdentifier - })).trim(); - } - - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } -} diff --git a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts b/src/postgres/commands/createPostgresQuery/validateIdentifier.ts deleted file mode 100644 index 9339f6796..000000000 --- a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ /dev/null @@ -1,113 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { localize } from "../../../utils/localize"; - -export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); - - const min = 1; - const max = 63; - - if (identifier.length < min || identifier.length > max) { - return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } - - if (!identifier[0].match(/[a-z_]/i)) { - return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); - } - - if (identifier.match(/[^a-z_\d$]/i)) { - return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); - } - - if (reservedWords.has(identifier.toLowerCase())) { - return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); - } - - return undefined; -} - -// Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html -const reservedWords: Set = new Set([ - 'all', - 'analyse', - 'analyze', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'asymmetric', - 'both', - 'case', - 'cast', - 'check', - 'collate', - 'column', - 'constraint', - 'create', - 'current_catalog', - 'current_date', - 'current_role', - 'current_time', - 'current_timestamp', - 'current_user', - 'default', - 'deferrable', - 'desc', - 'distinct', - 'do', - 'else', - 'end', - 'except', - 'false', - 'fetch', - 'for', - 'foreign', - 'from', - 'grant', - 'group', - 'having', - 'in', - 'initially', - 'intersect', - 'into', - 'lateral', - 'leading', - 'limit', - 'localtime', - 'localtimestamp', - 'not', - 'null', - 'offset', - 'on', - 'only', - 'or', - 'order', - 'placing', - 'primary', - 'references', - 'returning', - 'select', - 'session_user', - 'some', - 'symmetric', - 'table', - 'then', - 'to', - 'trailing', - 'true', - 'union', - 'unique', - 'user', - 'using', - 'variadic', - 'when', - 'where', - 'window', - 'with' -]); diff --git a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts deleted file mode 100644 index 390c1cf42..000000000 --- a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; - -export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; - - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts deleted file mode 100644 index 2f07d8203..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; - -export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize('confirmPW', 'Confirm your password'); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) - }); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } - - private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { - if (passphrase !== context.adminPassword) { - return localize('pwMatch', 'The passwords must match.'); - } - - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts deleted file mode 100644 index f73ce810d..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; -import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; -import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; - - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - - const locationName: string = (await LocationListStep.getLocation(context)).name; - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); - const newServerName = nonNullProp(context, 'newServerName'); - const password: string = nonNullProp(context, 'adminPassword'); - - return await callWithMaskHandling( - async () => { - const serverType = nonNullProp(context, 'serverType'); - const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); - - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, 'sku'), - administratorLogin: nonNullProp(context, 'shortUserName'), - administratorLoginPassword: password, - size: parseInt(size) - }; - - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); - context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); - context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, - password); - } - - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } - - - private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier - }, - } - } - - private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size - } - } - } - } - -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts deleted file mode 100644 index c48d40c37..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); - -export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, 'shortUserName'); - context.adminPassword = (await context.ui.showInputBox({ - placeHolder: localize('pwPlaceholder', 'Administrator Password'), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => validatePassword(user, password), - })); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } -} - -async function validatePassword(username: string, password: string): Promise { - password = password ? password : ''; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map(substring => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); - } else { - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts deleted file mode 100644 index 7b4890d07..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = (await context.ui.showInputBox({ - placeHolder: localize('usernamePlaceholder', 'Administrator Username'), - validateInput: validateUser, - })).trim(); - const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; - context.longUserName = context.shortUserName + usernameSuffix; - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } -} - -async function validateUser(username: string): Promise { - username = username ? username.trim() : ''; - - const min = 1; - const max = 63; - - const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; - - if (username.length < min || username.length > max) { - return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); - } else if (username.match(/^[0-9]+/)) { - return localize('usernameBeginningMatch', 'The name cannot start with a number.'); - } else if (username.toLowerCase().startsWith('pg_')) { - return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map(d => `"${d}"`).join(', '); - return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); - } else { - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts deleted file mode 100644 index 1af03f5c7..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ /dev/null @@ -1,60 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; -import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerNameStep extends AzureNameStep { - - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: localize('serverNamePlaceholder', 'Server name'), - prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), - validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} - -async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { - name = name ? name.trim() : ''; - - const min = 3; - const max = 63; - - if (name.length < min || name.length > max) { - return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } else if (!(/^[a-z0-9-]+$/).test(name)) { - return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); - } else if (name.startsWith('-') || name.endsWith('-')) { - return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); - } - const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); - - if (!availability.nameAvailable) { - return availability.message ? - availability.message : - localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); - } - - return undefined; - -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts deleted file mode 100644 index 3431e8f00..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; -import { setPostgresCredentials } from '../../setPostgresCredentials'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; - - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if (context.serverType && context.serverType === PostgresServerType.Single) { - user = nonNullProp(context, 'longUserName'); - } else { - user = nonNullProp(context, 'shortUserName'); - } - const newServerName: string = nonNullProp(context, 'newServerName'); - - const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, 'adminPassword'); - const server: PostgresAbstractServer = nonNullProp(context, 'server'); - - await setPostgresCredentials(user, password, nonNullProp(server, 'id')); - const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } - - public shouldExecute(): boolean { - return true; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts deleted file mode 100644 index 654cd0430..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ /dev/null @@ -1,250 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { openUrl } from "../../../../utils/openUrl"; -import { AbstractSku, PostgresServerType } from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; - -interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; -} - -export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresServerWizardContext - ): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); - pricingTiers.push({ - label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), - onPicked: async () => { - await openUrl('https://aka.ms/AAcxhvm'); - }, data: undefined - }); - - context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } - - public async getPicks(serverType: PostgresServerType): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; - - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: option.group || localize('addlOptions', 'Additional Options') - }); - }); - return options; - } -} - -const recommendedGroup = localize('recommendGroup', 'Recommended'); -const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, -]; - -// Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 -// See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage -const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, -]; diff --git a/src/postgres/commands/deletePostgresDatabase.ts b/src/postgres/commands/deletePostgresDatabase.ts deleted file mode 100644 index a09520bde..000000000 --- a/src/postgres/commands/deletePostgresDatabase.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; - -export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); - const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresFunction.ts b/src/postgres/commands/deletePostgresFunction.ts deleted file mode 100644 index 9a4547428..000000000 --- a/src/postgres/commands/deletePostgresFunction.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; - -export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } - - const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresServer.ts b/src/postgres/commands/deletePostgresServer.ts deleted file mode 100644 index 733c6fca6..000000000 --- a/src/postgres/commands/deletePostgresServer.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; -import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; - -export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - await deleteDatabaseAccount(context, node, true) -} diff --git a/src/postgres/commands/deletePostgresStoredProcedure.ts b/src/postgres/commands/deletePostgresStoredProcedure.ts deleted file mode 100644 index 6abece79b..000000000 --- a/src/postgres/commands/deletePostgresStoredProcedure.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; - -export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } - - const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresTable.ts b/src/postgres/commands/deletePostgresTable.ts deleted file mode 100644 index bfdce33a2..000000000 --- a/src/postgres/commands/deletePostgresTable.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; - -export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); - await node.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/enterPostgresCredentials.ts b/src/postgres/commands/enterPostgresCredentials.ts deleted file mode 100644 index aa993c337..000000000 --- a/src/postgres/commands/enterPostgresCredentials.ts +++ /dev/null @@ -1,85 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { PostgresServerType } from '../abstract/models'; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -import { setPostgresCredentials } from "./setPostgresCredentials"; - -/** - * Get the username and password for the Postgres database from user input. - */ -async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string, password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), - stepName: 'enterPostgresUsername', - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } - }); - - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { - username += usernameSuffix; - } - - const password: string = await context.ui.showInputBox({ - prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), - stepName: 'enterPostgresPassword', - password: true, - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } - }); - - return { username, password }; -} - -/** - * Save the username and password in secure local storage. - */ -async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { - const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); - - const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); -} - -export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, 'azureName'); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, 'id'); - - const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); - - await persistUsernamePassword(id, serverName, username, password); - - treeItem.setCredentials(username, password); - await treeItem.refresh(context); -} diff --git a/src/postgres/commands/executePostgresQueryInDocument.ts b/src/postgres/commands/executePostgresQueryInDocument.ts deleted file mode 100644 index af5d3ca5e..000000000 --- a/src/postgres/commands/executePostgresQueryInDocument.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { EOL } from 'os'; -import * as path from 'path'; -import { ClientConfig, QueryResult } from 'pg'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import * as vscodeUtil from '../../utils/vscodeUtils'; -import { runPostgresQuery } from '../runPostgresQuery'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; -import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; - -export async function executePostgresQueryInDocument(context: IActionContext): Promise { - await loadPersistedPostgresDatabase(); - - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); - - const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - - if (!activeEditor?.document) { - throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); - } - - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); - ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); - - if (queryResult.rowCount) { - const fileExtension: string = path.extname(activeEditor.document.fileName); - const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); - const outputFileName: string = `${queryFileName}-output`; - - const fields: string[] = queryResult.fields.map(f => f.name); - let csvData: string = `${fields.join(',')}${EOL}`; - - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(',')}${EOL}`; - } - - await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); - } - await treeItem.refresh(context); -} diff --git a/src/postgres/commands/openPostgresFunction.ts b/src/postgres/commands/openPostgresFunction.ts deleted file mode 100644 index 26103970f..000000000 --- a/src/postgres/commands/openPostgresFunction.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { showPostgresQuery } from "../showPostgresQuery"; -import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; - -export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } - - await showPostgresQuery(treeItem); -} diff --git a/src/postgres/commands/openPostgresStoredProcedure.ts b/src/postgres/commands/openPostgresStoredProcedure.ts deleted file mode 100644 index 3c98ff743..000000000 --- a/src/postgres/commands/openPostgresStoredProcedure.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { showPostgresQuery } from "../showPostgresQuery"; -import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; - -export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } - - await showPostgresQuery(treeItem); -} diff --git a/src/postgres/commands/registerPostgresCommands.ts b/src/postgres/commands/registerPostgresCommands.ts deleted file mode 100644 index b861e00f7..000000000 --- a/src/postgres/commands/registerPostgresCommands.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { defaults } from "pg"; -import { languages } from "vscode"; -import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { openUrl } from "../../utils/openUrl"; -import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { configurePostgresFirewall } from "./configurePostgresFirewall"; -import { connectPostgresDatabase } from "./connectPostgresDatabase"; -import { copyConnectionString } from "./copyConnectionString"; -import { createPostgresDatabase } from "./createPostgresDatabase"; -import { createPostgresFunctionQuery } from "./createPostgresQuery/function/createPostgresFunctionQuery"; -import { createPostgresStoredProcedureQuery } from "./createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery"; -import { deletePostgresDatabase } from "./deletePostgresDatabase"; -import { deletePostgresFunction } from "./deletePostgresFunction"; -import { deletePostgresServer } from "./deletePostgresServer"; -import { deletePostgresStoredProcedure } from "./deletePostgresStoredProcedure"; -import { deletePostgresTable } from "./deletePostgresTable"; -import { enterPostgresCredentials } from "./enterPostgresCredentials"; -import { executePostgresQueryInDocument } from "./executePostgresQueryInDocument"; -import { openPostgresFunction } from "./openPostgresFunction"; -import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; - -export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); - - void loadPersistedPostgresDatabase(); - - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; - - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); - registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); - registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); - registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); - registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); - registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); -} - -export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); - if (persistedTreeItem) { - await connectPostgresDatabase(context, persistedTreeItem); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); -} - -export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); -} diff --git a/src/postgres/commands/setPostgresCredentials.ts b/src/postgres/commands/setPostgresCredentials.ts deleted file mode 100644 index 8df8260f6..000000000 --- a/src/postgres/commands/setPostgresCredentials.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from "../../extensionVariables"; -import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; - -interface IPersistedServer { - id: string; - username: string; -} - -export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); - - const newServer: IPersistedServer = { - id: serverId, - username - }; - - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); -} diff --git a/src/postgres/getClientConfig.ts b/src/postgres/getClientConfig.ts deleted file mode 100644 index bdc545945..000000000 --- a/src/postgres/getClientConfig.ts +++ /dev/null @@ -1,172 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Client, ClientConfig } from "pg"; -import { ConnectionOptions } from "tls"; -import { postgresDefaultPort } from "../constants"; -import { nonNullProp } from "../utils/nonNull"; -import { PostgresServerType } from "./abstract/models"; -import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; - -export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; -}; -export type PostgresClientConfigType = keyof PostgresClientConfigs; - -/** - * Test if the database can be connected to using the given client config. - * @throws if the client failed to connect to the database. - */ -export async function testClientConfig(clientConfig: ClientConfig): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } -} - -async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString(connectionString, databaseName); - } - return { connectionString: connectionString }; -} - -async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; - - if (!!username && !!password && !!host && !!port) { - return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; - } else { - return undefined; - } -} - -async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise -): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; -} - -export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise -): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] - }; - const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { - const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); - clientConfigs.connectionString = connectionStringClientConfig; - } - - return clientConfigs; -} - -// Postgres Single Server Root Cert, https://aka.ms/AA7wnvl -export const BaltimoreCyberTrustRoot: string = `-----BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE-----`; - -// Postgres Single Server Root Cert will be updated to DigiCertGlobalRootG2, https://aka.ms/AA7wnvl -export const DigiCertGlobalRootG2: string = `-----BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE-----`; - -// Postgres Flexible Server Root Cert, https://aka.ms/AAd75x5 -export const DigiCertGlobalRootCA: string = `-----BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE-----`; - diff --git a/src/postgres/getPostgresProcedureQueryRows.ts b/src/postgres/getPostgresProcedureQueryRows.ts deleted file mode 100644 index ad791ff2e..000000000 --- a/src/postgres/getPostgresProcedureQueryRows.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { QueryResult } from "pg"; -import { runPostgresQuery } from "./runPostgresQuery"; -import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; -import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; - -export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; -} - -function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, - p.proname as name, - p.oid as oid, - pg_get_function_arguments(p.oid) as args, - case when l.lanname = 'internal' then p.prosrc - else pg_get_functiondef(p.oid) - end as definition - from pg_proc p - left join pg_namespace n on p.pronamespace = n.oid - left join pg_language l on p.prolang = l.oid - where n.nspname not in ('pg_catalog', 'information_schema') - ${conditions} - order by name;`; -} - -export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { - let conditions: string; - - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } - - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } - - return rows; -} diff --git a/src/postgres/getTables.ts b/src/postgres/getTables.ts deleted file mode 100644 index ebc7d1c75..000000000 --- a/src/postgres/getTables.ts +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ClientConfig, QueryResult } from "pg"; -import { runPostgresQuery } from "./runPostgresQuery"; - -export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; -} - -const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, - concat('"', schemaname, '"."', tablename, '"')::regclass::oid as oid - from pg_catalog.pg_tables - left join ( - select column_name::text as columnname, table_name, table_schema - from information_schema.columns - ) columns on table_name = tablename and table_schema = schemaname - where schemaname != 'pg_catalog' AND schemaname != 'information_schema' - group by schemaname, tablename;`; - -export async function getTables(clientConfig: ClientConfig): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); - } - return tablesArray; -} diff --git a/src/postgres/postgresConnectionStrings.ts b/src/postgres/postgresConnectionStrings.ts deleted file mode 100644 index ea9ce9e2e..000000000 --- a/src/postgres/postgresConnectionStrings.ts +++ /dev/null @@ -1,74 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConnectionOptions, parse } from "pg-connection-string"; -import { postgresDefaultPort } from "../constants"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullProp } from "../utils/nonNull"; - -export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); -} - -export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); -} - -export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; -} - -export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; -} - -export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; - - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, 'host'); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } -} diff --git a/src/postgres/postgresConstants.ts b/src/postgres/postgresConstants.ts deleted file mode 100644 index 9bcf15144..000000000 --- a/src/postgres/postgresConstants.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export const invalidCredentialsErrorType: string = '28P01'; -export const firewallNotConfiguredErrorType: string = '28000'; -export const timeoutErrorType = 'ETIMEDOUT'; diff --git a/src/postgres/runPostgresQuery.ts b/src/postgres/runPostgresQuery.ts deleted file mode 100644 index b7d325364..000000000 --- a/src/postgres/runPostgresQuery.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Client, ClientConfig, QueryResult } from "pg"; - -export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } -} -export function wrapArgInQuotes(input: string): string { - return `"${input}"`; -} diff --git a/src/postgres/services/PostgresCodeLensProvider.ts b/src/postgres/services/PostgresCodeLensProvider.ts deleted file mode 100644 index 5d075eb3c..000000000 --- a/src/postgres/services/PostgresCodeLensProvider.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; -import { localize } from "../../utils/localize"; - -export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; - - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } - - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } - - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; - - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; - - let title: string; - if (!isInitialized) { - title = localize('initializing', 'Initializing...'); - } else if (isConnected) { - title = localize('connectedToDatabase', 'Connected to "{0}"', database); - } else { - title = localize('connectToDatabase', 'Connect to a database'); - } - - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && 'postgreSQL.connectDatabase' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - - if (isConnected) { - lenses.push({ - command: { - title: 'Execute Query', - command: 'postgreSQL.executeQuery' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - } - - return lenses; - }); - } -} diff --git a/src/postgres/showPostgresQuery.ts b/src/postgres/showPostgresQuery.ts deleted file mode 100644 index 7d6e2aa1d..000000000 --- a/src/postgres/showPostgresQuery.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { postgresBaseFileName, postgresFileExtension } from '../constants'; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; -import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; - -export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); -} diff --git a/src/postgres/tree/ClientConfigFactory.ts b/src/postgres/tree/ClientConfigFactory.ts deleted file mode 100644 index 271f5b92f..000000000 --- a/src/postgres/tree/ClientConfigFactory.ts +++ /dev/null @@ -1,86 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; -import { localize } from "../../utils/localize"; -import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; -import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; - -export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; - -/** - * Creates an object that can be used to execute a postgres query with connection test and telemetry. - */ -export class PostgresClientConfigFactory { - public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ - type: "azureAd" | "password" | "connectionString", - clientConfig: ClientConfig - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); - - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); - - const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; - - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } - - try { - await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = clientConfigType; - await testClientConfig(clientConfig); - }); - return { - type: clientConfigType, - clientConfig - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), - code: firewallNotConfiguredErrorType - }; - } else { - throw error; - } - } - } - - throw { - message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), - code: invalidCredentialsErrorType - }; - } -} diff --git a/src/postgres/tree/PostgresColumnTreeItem.ts b/src/postgres/tree/PostgresColumnTreeItem.ts deleted file mode 100644 index d284c8122..000000000 --- a/src/postgres/tree/PostgresColumnTreeItem.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; - -export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; - - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } - - public get id(): string { - return this.columnName; - } - - public get label(): string { - return this.columnName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('split-horizontal'); - } - -} diff --git a/src/postgres/tree/PostgresDatabaseTreeItem.ts b/src/postgres/tree/PostgresDatabaseTreeItem.ts deleted file mode 100644 index 05f7a4412..000000000 --- a/src/postgres/tree/PostgresDatabaseTreeItem.ts +++ /dev/null @@ -1,115 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// eslint-disable-next-line import/no-internal-modules -import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { ThemeIcon } from 'vscode'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresServerTreeItem } from './PostgresServerTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; - - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresFirewall', - label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.configureFirewall' - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } - - try { - const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig) - ]; - - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); - } - - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); - - if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresCredentials', - label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.enterCredentials' - }); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - return []; - } else { - throw error; - } - } - } - - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); - } - - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); - await this.refresh(context); - } -} diff --git a/src/postgres/tree/PostgresFunctionTreeItem.ts b/src/postgres/tree/PostgresFunctionTreeItem.ts deleted file mode 100644 index 0a26bf3f9..000000000 --- a/src/postgres/tree/PostgresFunctionTreeItem.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { IPostgresProceduresQueryRow } from "../getPostgresProcedureQueryRows"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; - -export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresFunction'; - public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; - - constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openFunction'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } - - public get label(): string { - return this.name; - } - - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); - } -} diff --git a/src/postgres/tree/PostgresFunctionsTreeItem.ts b/src/postgres/tree/PostgresFunctionsTreeItem.ts deleted file mode 100644 index 7d3904e83..000000000 --- a/src/postgres/tree/PostgresFunctionsTreeItem.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; - -export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresFunctions'; - public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; - public readonly label: string = 'Functions'; - public readonly childTypeLabel: string = 'Function'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } -} diff --git a/src/postgres/tree/PostgresResourcesTreeItemBase.ts b/src/postgres/tree/PostgresResourcesTreeItemBase.ts deleted file mode 100644 index b93cc9450..000000000 --- a/src/postgres/tree/PostgresResourcesTreeItemBase.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; - -// Base class for Postgres tree items whose children are individual resources -export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } - - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } -} diff --git a/src/postgres/tree/PostgresServerTreeItem.ts b/src/postgres/tree/PostgresServerTreeItem.ts deleted file mode 100644 index 20e7dbe76..000000000 --- a/src/postgres/tree/PostgresServerTreeItem.ts +++ /dev/null @@ -1,252 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as SingleModels from '@azure/arm-postgresql'; -import * as FlexibleModels from '@azure/arm-postgresql-flexible'; -import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import { ClientConfig } from 'pg'; -import { SemVer, coerce, gte } from 'semver'; -import * as vscode from 'vscode'; -import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { isIpInRanges } from '../../utils/getIp'; -import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; -import { getPublicIp } from '../commands/configurePostgresFirewall'; -import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -interface IPersistedServer { - id: string; - username: string; -} - -export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; - } - this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('PostgresServer.svg'); - } - - public get label(): string { - return this.azureName ? this.azureName : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); - dbNames = listOfDatabases.map(db => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map(db => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - 'invalidPostgresServer', - dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, - dbName => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); - } - const getChildrenTask: Promise = this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createPostgresDatabase', - validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) - }); - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, '11.0.0'); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); - - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); - } - - public async getFullConnectionString(): Promise { - - if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { - const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp(this, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); - const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } -} - -async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { - if (!name) { - return localize('NameCannotBeEmpty', 'Name cannot be empty.'); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize('NameExists', 'Database "{0}" already exists.', name); - } - return undefined; -} diff --git a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts b/src/postgres/tree/PostgresStoredProcedureTreeItem.ts deleted file mode 100644 index 503d0ae74..000000000 --- a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { IPostgresProceduresQueryRow } from "../getPostgresProcedureQueryRows"; -import { runPostgresQuery } from "../runPostgresQuery"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; - -export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresStoredProcedure'; - public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; - - constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openStoredProcedure'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } - - public get label(): string { - return this.name; - } - - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); - } -} diff --git a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts b/src/postgres/tree/PostgresStoredProceduresTreeItem.ts deleted file mode 100644 index 1c516e00f..000000000 --- a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; - -export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresStoredProcedures'; - public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = 'Stored Procedures'; - public readonly childTypeLabel: string = 'Stored Procedure'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } -} diff --git a/src/postgres/tree/PostgresTableTreeItem.ts b/src/postgres/tree/PostgresTableTreeItem.ts deleted file mode 100644 index ef5d87c2c..000000000 --- a/src/postgres/tree/PostgresTableTreeItem.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IPostgresTable } from '../getTables'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; - - private _isDuplicate: boolean; - - constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } - - public get id(): string { - return String(this.table.oid); - } - - public get label(): string { - return this.table.name; - } - - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); - } - -} diff --git a/src/postgres/tree/PostgresTablesTreeItem.ts b/src/postgres/tree/PostgresTablesTreeItem.ts deleted file mode 100644 index c18c065db..000000000 --- a/src/postgres/tree/PostgresTablesTreeItem.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from 'vscode'; -import { getTables, IPostgresTable } from "../getTables"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; - -export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = 'Tables'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); - } - return tables.map(table => new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } -} diff --git a/src/resolver/AppResolver.ts b/src/resolver/AppResolver.ts deleted file mode 100644 index 0f75cdf29..000000000 --- a/src/resolver/AppResolver.ts +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; -import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; -import { tryGetExperience } from "../AzureDBExperiences"; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from "../extensionVariables"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { PostgresAbstractServer } from "../postgres/abstract/models"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; -import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; -import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; - -const resourceTypes = [ - 'microsoft.documentdb/databaseaccounts', - 'microsoft.dbforpostgresql/servers', - 'microsoft.dbforpostgresql/flexibleservers' -]; - -export class DatabaseResolver implements AppResourceResolver { - public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { - return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); - try { - const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); - const name = nonNullProp(resource, 'name'); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; - - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ ...context, ...subContext }); - const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); - const experience = tryGetExperience(databaseAccount); - - return experience?.api === 'MongoDB' ? - new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : - new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? - await createPostgreSQLClient({ ...context, ...subContext }) : - await createPostgreSQLFlexibleClient({ ...context, ...subContext }); - - postgresServer = await postgresClient.servers.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); - - return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - }); - } - - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } -} diff --git a/src/resolver/DatabaseWorkspaceProvider.ts b/src/resolver/DatabaseWorkspaceProvider.ts deleted file mode 100644 index 14e50d643..000000000 --- a/src/resolver/DatabaseWorkspaceProvider.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; -import { Disposable } from "vscode"; -import { ext } from "../extensionVariables"; -import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; - - -export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise { - - return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - }); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } -} - diff --git a/src/resolver/ResolvedDatabaseAccountResource.ts b/src/resolver/ResolvedDatabaseAccountResource.ts deleted file mode 100644 index 0222dded7..000000000 --- a/src/resolver/ResolvedDatabaseAccountResource.ts +++ /dev/null @@ -1,57 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; - -export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue) - this.maskedValuestoAdd.push(...ti.valuesToMask); - } -} diff --git a/src/resolver/ResolvedDocDBAccountResource.ts b/src/resolver/ResolvedDocDBAccountResource.ts deleted file mode 100644 index cf1bfc4bc..000000000 --- a/src/resolver/ResolvedDocDBAccountResource.ts +++ /dev/null @@ -1,32 +0,0 @@ - - -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } -} diff --git a/src/resolver/ResolvedMongoAccountResource.ts b/src/resolver/ResolvedMongoAccountResource.ts deleted file mode 100644 index 4f45486ef..000000000 --- a/src/resolver/ResolvedMongoAccountResource.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - root: IMongoTreeRoot; - - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - } -} diff --git a/src/resolver/ResolvedPostgresServerResource.ts b/src/resolver/ResolvedPostgresServerResource.ts deleted file mode 100644 index a1e35acf3..000000000 --- a/src/resolver/ResolvedPostgresServerResource.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { ClientConfig } from "pg"; -import { PostgresServerType } from "../postgres/abstract/models"; -import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise - deletePostgresCredentials: () => Promise - getFullConnectionString: () => Promise - validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise - isFirewallRuleSet: (context: IActionContext) => Promise - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } -} diff --git a/src/table/tree/TableAccountTreeItem.ts b/src/table/tree/TableAccountTreeItem.ts deleted file mode 100644 index 0d3b86e38..000000000 --- a/src/table/tree/TableAccountTreeItem.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; - -export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public initChild(): AzExtTreeItem { - throw new Error('Table Accounts are not supported yet.'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'tableNotSupported', - label: 'Table Accounts are not supported yet.' - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } - - public isAncestorOfImpl(): boolean { - return false; - } -} diff --git a/src/tree/AttachedAccountsTreeItem.ts b/src/tree/AttachedAccountsTreeItem.ts deleted file mode 100644 index d854e506f..000000000 --- a/src/tree/AttachedAccountsTreeItem.ts +++ /dev/null @@ -1,420 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { removeTreeItemFromCache } from '../commands/api/apiCache'; -import { emulatorPassword, isWindows } from '../constants'; -import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; -import { connectToMongoClient } from '../mongo/connectToMongoClient'; -import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; -import { getSecretStorageKey } from '../utils/getSecretStorageKey'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; - -interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; -} - -export const AttachedAccountSuffix: string = 'Attached'; -export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; - -const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; - -export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); - public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; - public readonly label: string = 'Attached Database Accounts'; - public childTypeLabel: string = 'Account'; - public suppressMaskLabel = true; - - private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = 'cosmosDBAttachedAccounts'; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('plug'); - } - - public static validateMongoConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); - } - - private static validateDocDBConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachDatabaseAccount', - label: 'Attach Database Account...', - commandId: 'cosmosDB.attachDatabaseAccount', - includeInTreeItemPicker: true - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachEmulator', - label: 'Attach Emulator...', - commandId: 'cosmosDB.attachEmulator', - includeInTreeItemPicker: true - }); - return isWindows ? [attachDatabaseAccount, attachEmulator] : - [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = 'mongodb://host:port'; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; - } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { - placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); - validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = 'AccountEndpoint=...;AccountKey=...'; - validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = (await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: 'Enter the connection string for your database account', - stepName: 'attachNewAccountConnectionString', - validateInput: validateInput, - value: defaultValue - })).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { - const treeItem = await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core) - ], - { - placeHolder: "Select a Database Account API...", - stepName: 'attachEmulator' - }); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); - if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.find(s => s.id === treeItem.id)) { - void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get(this._serviceName); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all(accounts.map(async account => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof (account) === 'string') { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${getExperienceFromApi(api).shortName})`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); - persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); - })); - } - - return persistedAccounts; - } - - private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error(`Unexpected account node "${node.constructor.name}".`); - } - return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; - }); - await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); - } -} - -class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); - - public get credentials(): never { - throw this._error; - } - - public get subscriptionDisplayName(): never { - throw this._error; - } - - public get subscriptionId(): never { - throw this._error; - } - - public get subscriptionPath(): never { - throw this._error; - } - - public get tenantId(): never { - throw this._error; - } - - public get userId(): never { - throw this._error; - } - - public get environment(): never { - throw this._error; - } - - public get isCustomCloud(): never { - throw this._error; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} diff --git a/src/tree/AzureAccountTreeItemWithAttached.ts b/src/tree/AzureAccountTreeItemWithAttached.ts deleted file mode 100644 index 172cd598f..000000000 --- a/src/tree/AzureAccountTreeItemWithAttached.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; -import { ext } from '../extensionVariables'; -import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; - -export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } - - public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } - - public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); - return children.concat(ext.attachedAccountsNode); - } - - public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } -} diff --git a/src/tree/AzureDBAPIStep.ts b/src/tree/AzureDBAPIStep.ts deleted file mode 100644 index 8a11fdc95..000000000 --- a/src/tree/AzureDBAPIStep.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; -import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; -import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; -import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; -import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; -import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; -import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; -import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; -import { localize } from '../utils/localize'; -import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; -import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; -import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; -import { IAzureDBWizardContext } from './IAzureDBWizardContext'; - -export class AzureDBAPIStep extends AzureWizardPromptStep { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); - - const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { - placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') - }); - - context.defaultExperience = result.data; - } - - public async getSubWizard(context: IAzureDBWizardContext): Promise> { - let promptSteps: AzureWizardPromptStep[]; - let executeSteps: AzureWizardExecuteStep[]; - if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(['Microsoft.DocumentDB']) - ]; - } - return { promptSteps, executeSteps }; - } - - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts deleted file mode 100644 index b46453e3a..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { - - public async prompt(context: ICosmosDBWizardContext): Promise { - - const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') - const picks: IAzureQuickPickItem[] = [ - { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, - { label: localize('serverlessOption', 'Serverless'), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; - - do { - pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); - if (pick === learnMore) { - await openUrl('https://aka.ms/cosmos-models'); - } - } while (pick === learnMore); - - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; - } - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts deleted file mode 100644 index 4bd469b84..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ /dev/null @@ -1,63 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; -import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { Progress } from 'vscode'; -import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const locationName: string = (await LocationListStep.getLocation(context)).name; - const defaultExperience = nonNullProp(context, 'defaultExperience'); - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const accountName = nonNullProp(context, 'newServerName'); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: 'Standard', - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, - }; - - if (defaultExperience?.api === 'MongoDB') { - options.apiProperties = { serverVersion: '3.6' }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts deleted file mode 100644 index 87ef6be61..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountNameStep extends AzureNameStep { - - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => validateCosmosDBAccountName(name, client) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} - -async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { - name = name ? name.trim() : ''; - - const min = 3; - const max = 31; - - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } -} diff --git a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts deleted file mode 100644 index 61666a859..000000000 --- a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; - -export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; - -} diff --git a/src/tree/IAzureDBWizardContext.ts b/src/tree/IAzureDBWizardContext.ts deleted file mode 100644 index fd84ff0d5..000000000 --- a/src/tree/IAzureDBWizardContext.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { Experience } from '../AzureDBExperiences'; - -export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - - newServerName?: string; - defaultExperience?: Experience; - -} diff --git a/src/tree/SubscriptionTreeItem.ts b/src/tree/SubscriptionTreeItem.ts deleted file mode 100644 index 910d8d970..000000000 --- a/src/tree/SubscriptionTreeItem.ts +++ /dev/null @@ -1,158 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; -import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from '../extensionVariables'; -import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; -import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from '../utils/activityUtils'; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { localize } from '../utils/localize'; -import { nonNullProp } from '../utils/nonNull'; -import { AzureDBAPIStep } from './AzureDBAPIStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; - -export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = 'Account'; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - - //Postgres - const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); - const postgresServers: PostgresAbstractServer[] = [ - ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), - ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), - ]; - - const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - postgresServers, - 'invalidPostgreSQLAccount', - async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); - const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - accounts, - 'invalidCosmosDBAccount', - async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep() - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize('createDBServerMsg', 'Create new Azure Database Server') - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp(wizardContext, 'newServerName'); - wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { - const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, 'server'); - const host = nonNullProp(server, 'fullyQualifiedDomainName'); - const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); - const password: string = nonNullProp(wizardContext, 'adminPassword'); - const connectionString: string = createPostgresConnectionString(host, undefined, username, password); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return typeof contextValue !== 'string' || !/attached/i.test(contextValue); - } - - public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, 'id'); - const name: string = nonNullProp(databaseAccount, 'name'); - const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); - const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = 'retrywrites'; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, 'false'); - } - - // Use the default connection string - return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); - } else { - const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - case "Graph": { - const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); - return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - - } - } - } - public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { - const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } -} diff --git a/src/utils/InteractiveChildProcess.ts b/src/utils/InteractiveChildProcess.ts deleted file mode 100644 index 26129b342..000000000 --- a/src/utils/InteractiveChildProcess.ts +++ /dev/null @@ -1,176 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as cp from 'child_process'; -import * as os from 'os'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { Event, EventEmitter } from 'vscode'; -import { improveError } from './improveError'; - -// We add these when we display to the output window -const stdInPrefix = '> '; -const stdErrPrefix = 'ERR> '; -const errorPrefix = 'Error running process: '; - -const processStartupTimeout = 60; - -export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; -} - -export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create(options: IInteractiveChildProcessOptions): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess(options); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(' '); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false - }; - - this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); - this._childProc = cp.spawn(this._options.command, this._options.args, options); - - this._childProc.stdout?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on('error', (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on('close', (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel(text: string, displayPrefix?: string): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = (filteredText !== text && filteredText === ''); - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); - } - - return text; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} diff --git a/src/utils/activityUtils.ts b/src/utils/activityUtils.ts deleted file mode 100644 index fefd2fe00..000000000 --- a/src/utils/activityUtils.ts +++ /dev/null @@ -1,15 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { ext } from "../extensionVariables"; -import { getWorkspaceSetting } from "./settingUtils"; - -export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), - }; -} diff --git a/src/utils/array.ts b/src/utils/array.ts deleted file mode 100644 index 06f095e8d..000000000 --- a/src/utils/array.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { - return arr ? arr.filter(element => element instanceof genericConstructor) : []; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { - return arr && arr.find(element => element instanceof genericConstructor); -} diff --git a/src/utils/azureClients.ts b/src/utils/azureClients.ts deleted file mode 100644 index 9be19e959..000000000 --- a/src/utils/azureClients.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; -import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; - -// Lazy-load @azure packages to improve startup performance. -// NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript - -export async function createCosmosDBClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); -} - -export async function createPostgreSQLClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); -} - -export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); -} diff --git a/src/utils/azureUtils.ts b/src/utils/azureUtils.ts deleted file mode 100644 index b0017314b..000000000 --- a/src/utils/azureUtils.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); - - if (!matches || matches.length < 5) { - throw new Error('Invalid Azure Resource Id'); - } - - return matches[4]; -} diff --git a/src/utils/cp.ts b/src/utils/cp.ts deleted file mode 100644 index 660dc3068..000000000 --- a/src/utils/cp.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as cp from 'child_process'; - -export async function commandSucceeds(command: string, ...args: string[]): Promise { - return await new Promise(resolve => { - cp.spawn(command, args) - .on('error', _error => resolve(false)) - .on('exit', code => resolve(code === 0)); - }); -} diff --git a/src/utils/getIp.ts b/src/utils/getIp.ts deleted file mode 100644 index 20d22e989..000000000 --- a/src/utils/getIp.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { isIPv4 } from 'net'; -import { localize } from './localize'; - -export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); -} - -export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, 'https://api.ipify.org/'), - () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; -} - -const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); - -function ipToNum(ip: string) { - return Number( - ip.split(".") - .map(d => ("000" + d).substring(-3)) - .join("") - ); -} - -async function getPublicIpv4Https(context: IActionContext, url: string): Promise { - const req = await sendRequestWithTimeout(context, { - method: 'GET', - url, - }, 5000, undefined); - - const ip = req.bodyAsText; - - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } - - return ip; -} diff --git a/src/utils/getSecretStorageKey.ts b/src/utils/getSecretStorageKey.ts deleted file mode 100644 index 80e116737..000000000 --- a/src/utils/getSecretStorageKey.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; -} diff --git a/src/utils/improveError.ts b/src/utils/improveError.ts deleted file mode 100644 index 27ff1f014..000000000 --- a/src/utils/improveError.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from "@microsoft/vscode-azext-utils"; - -export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } - - return error; -} diff --git a/src/utils/localize.ts b/src/utils/localize.ts deleted file mode 100644 index 2aee3fa12..000000000 --- a/src/utils/localize.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vscode-nls'; - -export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/src/utils/nonNull.ts b/src/utils/nonNull.ts deleted file mode 100644 index d7104b4f8..000000000 --- a/src/utils/nonNull.ts +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { isNullOrUndefined } from 'util'; - -/** - * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed - * for the property and will give a compile error if the given name is not a property of the source. - */ -export function nonNullProp(source: TSource, name: TKey): NonNullable { - const value: NonNullable = >source[name]; - return nonNullValue(value, name); -} - -/** - * Validates that a given value is not null and not undefined. - */ -export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { - if (isNullOrUndefined(value)) { - throw new Error( - 'Internal error: Expected value to be neither null nor undefined' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } - - return value; -} - -/** - * Validates that a given string is not null, undefined, nor empty - */ -export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { - if (!value) { - throw new Error( - 'Internal error: Expected value to be neither null, undefined, nor empty' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } - - return value; -} diff --git a/src/utils/openUrl.ts b/src/utils/openUrl.ts deleted file mode 100644 index 0be3f5bbb..000000000 --- a/src/utils/openUrl.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as open from 'open'; - -export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); - - await open(url); -} diff --git a/src/utils/randomUtils.ts b/src/utils/randomUtils.ts deleted file mode 100644 index 7a313f23a..000000000 --- a/src/utils/randomUtils.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as crypto from "crypto"; - -export namespace randomUtils { - export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { - return crypto.createHash('sha256').update(s).digest(encoding); - } - - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString('hex').slice(0, length); - } -} diff --git a/src/utils/settingUtils.ts b/src/utils/settingUtils.ts deleted file mode 100644 index 0ac1004c2..000000000 --- a/src/utils/settingUtils.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; -import { ext } from "../extensionVariables"; - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - await projectConfiguration.update(section, value, ConfigurationTarget.Global); -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); - return result && result.globalValue; -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); - return projectConfiguration.get(key); -} - -/** - * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } -} diff --git a/src/utils/timeout.ts b/src/utils/timeout.ts deleted file mode 100644 index cc5ffb2d6..000000000 --- a/src/utils/timeout.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -const timedOutMessage = "Execution timed out"; - -/** - * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. - */ -export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } - - throw err; - } -} - -/** - * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. - */ -export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout( - () => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, - timeoutMs); - - let value: T; - let error; - - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); -} diff --git a/src/utils/vscodeUtils.ts b/src/utils/vscodeUtils.ts deleted file mode 100644 index d05f84872..000000000 --- a/src/utils/vscodeUtils.ts +++ /dev/null @@ -1,103 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ItemDefinition } from '@azure/cosmos'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; -import { getRootPath } from './workspacUtils'; - -export interface IDisposable { - dispose(): void; -} - -export function dispose(disposables: T[]): T[] { - disposables.forEach(d => d.dispose()); - return []; -} - -export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; -} - -export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); - const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); - await writeToEditor(editor, data); -} - -export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt(editor.document.lineCount - 1); - editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); - } - - editBuilder.insert(new vscode.Position(0, 0), data); - }); -} - -async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { - let count: number = 1; - const maxCount: number = 1024; - - while (count < maxCount) { - const fileSuffix = count === 0 ? '' : '-' + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; - - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } - - throw new Error('Could not find unique name for new file.'); -} - -export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join('/'); -} - -function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); -} - -export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== 'object') { - return String(value); - } - } - } - return String(document._id); -} - -function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; -} diff --git a/src/utils/workspacUtils.ts b/src/utils/workspacUtils.ts deleted file mode 100644 index 20b60da11..000000000 --- a/src/utils/workspacUtils.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { nonNullValue } from './nonNull'; - -export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; -} - -export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); -} diff --git a/src/utils/wrapError.ts b/src/utils/wrapError.ts deleted file mode 100644 index f6ec5d2b5..000000000 --- a/src/utils/wrapError.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; - -export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } - - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } - - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); -} diff --git a/src/vscode-cosmosdb.api.d.ts b/src/vscode-cosmosdb.api.d.ts deleted file mode 100644 index d5e4416c1..000000000 --- a/src/vscode-cosmosdb.api.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem(query: TreeItemQuery): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; -} - -export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; -} - -export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - } - - docDBData?: { - masterKey: string; - documentEndpoint: string; - } - - postgresData?: { - username: string | undefined; - password: string | undefined; - } - -} - -export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; -} - -export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; - -export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; - -export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; -} - -export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - } -} diff --git a/src/vscode-cosmosdbgraph.api.d.ts b/src/vscode-cosmosdbgraph.api.d.ts deleted file mode 100644 index 95cde2531..000000000 --- a/src/vscode-cosmosdbgraph.api.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface CosmosDBGraphExtensionApi { - apiVersion: string; - - openGraphExplorer(config: IGraphConfiguration): Promise; -} - -export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; -} - -export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; - - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; - - key: string; - databaseName: string; - graphName: string; - tabTitle: string; -} From 3eedf2d82ee2019aab7e8c5ff1f7e6b3f4c56db3 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Tue, 14 Nov 2023 23:52:42 +0200 Subject: [PATCH 13/33] squash! --- .github/CODEOWNERS | 1 - .github/workflows/bump-version-pr.yaml | 30 ----------------- .github/workflows/feature-request.yml | 43 ------------------------ .github/workflows/info-needed-closer.yml | 27 --------------- .github/workflows/locker.yml | 24 ------------- 5 files changed, 125 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/bump-version-pr.yaml delete mode 100644 .github/workflows/feature-request.yml delete mode 100644 .github/workflows/info-needed-closer.yml delete mode 100644 .github/workflows/locker.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index f426a03c5..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @Microsoft/vscodeazuretoolsdev diff --git a/.github/workflows/bump-version-pr.yaml b/.github/workflows/bump-version-pr.yaml deleted file mode 100644 index dec36e0a9..000000000 --- a/.github/workflows/bump-version-pr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Bump version after release - -# Run when release is published, or manually triggered -on: - release: - types: [published] - workflow_dispatch: - -jobs: - bump: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Bump version - id: bump - uses: alexweininger/bump-prerelease-version@v0.1.1 - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - title: ${{ env.MESSAGE }} - body: Automatically created by ${{ env.RUN_LINK }} - commit-message: ${{ env.MESSAGE }} - branch: bot/bump-${{ steps.bump.outputs.new-version }} - base: main - author: GitHub - env: - RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - MESSAGE: Bump version after release diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml deleted file mode 100644 index 94c0c5144..000000000 --- a/.github/workflows/feature-request.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Feature Request Manager -on: - issues: - types: [milestoned] - schedule: - - cron: 15 5 * * * # 10:15pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: actions/checkout@v3 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - run: npm install --production --prefix ./actions - - name: Run Feature Request Manager - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: ./actions/feature-request - with: - token: ${{secrets.AZCODE_BOT_PAT}} - candidateMilestoneID: 28 - candidateMilestoneName: "Backlog Candidates" - backlogMilestoneID: 33 - featureRequestLabel: "feature" - upvotesRequired: 5 - numCommentsOverride: 10 - initComment: "This feature request is now a candidate for our backlog. The community has 240 days to upvote the issue. If it receives 5 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectComment: ":slightly_frowning_face: In the last 60 days, this issue has received less than 5 community upvotes and we closed it. Still a big Thank You to you for taking the time to create it! To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectLabel: "out of scope" - warnComment: "This issue has become stale and is at risk of being closed. The community has 60 days to upvote the issue. If it receives 5 upvotes we will keep it open and take another look. If not, we will close it. To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - labelsToExclude: "P0,P1" - acceptComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - warnDays: 60 - closeDays: 240 - milestoneDelaySeconds: 60 - diff --git a/.github/workflows/info-needed-closer.yml b/.github/workflows/info-needed-closer.yml deleted file mode 100644 index 9304007a4..000000000 --- a/.github/workflows/info-needed-closer.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Info Needed Closer -on: - schedule: - - cron: 30 5 * * * # 10:30pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Info Needed Closer - uses: ./actions/needs-more-info-closer - with: - token: ${{secrets.AZCODE_BOT_PAT}} - label: info-needed - closeDays: 14 - closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/azcodeissuereporting) guidelines.\n\nHappy Coding!" - pingDays: 80 - pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information." diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml deleted file mode 100644 index 050406703..000000000 --- a/.github/workflows/locker.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Locker -on: - schedule: - - cron: 0 5 * * * # 10:00pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Locker - uses: ./actions/locker - with: - token: ${{secrets.AZCODE_BOT_PAT}} - daysSinceClose: 45 - daysSinceUpdate: 7 From e3994b8871f04ff1546a40b50c4890814406f574 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Wed, 15 Nov 2023 20:02:05 +0200 Subject: [PATCH 14/33] squash! --- package-lock.json | 21347 -------------------------------------------- package.json | 108 +- 2 files changed, 54 insertions(+), 21401 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e16bd2f53..000000000 --- a/package-lock.json +++ /dev/null @@ -1,21347 +0,0 @@ -{ - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "license": "SEE LICENSE IN LICENSE.md", - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "engines": { - "vscode": "^1.66.0" - } - }, - "node_modules/@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@azure/abort-controller/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "node_modules/@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-cosmosdb/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-subscriptions/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-auth/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-client/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-lro/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "dependencies": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-paging/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-tracing/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-util/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/cosmos/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/cosmos/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/logger/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "node_modules/@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - } - }, - "node_modules/@azure/ms-rest-js/node_modules/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, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "dependencies": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "dependencies": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - }, - "peerDependencies": { - "tslib": "*" - } - }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "node_modules/@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "dependencies": { - "@typescript-eslint/parser": "^4.28.5" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=4", - "eslint": ">=7", - "eslint-plugin-import": ">=2" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "dependencies": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "dependencies": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "bin": { - "vscode-sort-package-json": "scripts/sortPackageJson.mjs" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "dependencies": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - }, - "node_modules/@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "dependencies": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "node_modules/@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "dependencies": { - "@types/webpack": "*" - } - }, - "node_modules/@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "node_modules/@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "dependencies": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "node_modules/@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "dependencies": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - } - }, - "node_modules/@types/gulp/node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/gulp/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@types/gulp/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@types/gulp/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/gulp/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/@types/gulp/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/@types/gulp/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "node_modules/@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "dependencies": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "node_modules/@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "node_modules/@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "node_modules/@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/uglify-js/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "node_modules/@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "node_modules/@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "dependencies": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "node_modules/@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "node_modules/@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "dependencies": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/webpack/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "dependencies": { - "fast-memoize": "^2.3.2" - } - }, - "node_modules/@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "dependencies": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - }, - "engines": { - "vscode": "^1.60.0" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/@vscode/test-electron/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "engines": { - "node": ">= 0.6.15" - } - }, - "node_modules/adal-node/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "node_modules/antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true, - "bin": { - "antlr4ts": "antlr4ts" - } - }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "dependencies": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - }, - "engines": { - "node": ">=8.9.0" - }, - "peerDependencies": { - "webpack": "*" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "node_modules/copy-props/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "dependencies": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/copy-webpack-plugin/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/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, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true, - "engines": { - "node": ">0.4.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "dev": true - }, - "node_modules/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 - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/enquirer/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/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 - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-glob/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli/node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, - "engines": { - "node": ">=10.23.2" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "dependencies": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/indexable-array/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/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 - }, - "node_modules/log-symbols/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true, - "engines": { - "node": ">= 6.14.4" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "peerDependencies": { - "mocha": ">=2.2.5" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-junit-reporter/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha-junit-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - } - }, - "node_modules/mocha-multi-reporters/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/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 - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - }, - "peerDependenciesMeta": { - "aws4": { - "optional": true - }, - "bson-ext": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "mongodb-extjson": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "dependencies": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/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, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "dependencies": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dependencies": { - "split": "^1.0.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "dependencies": { - "parseley": "^0.7.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/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 - }, - "node_modules/slice-ansi/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-color/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/table/node_modules/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/tas-client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tmp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "dependencies": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "engines": { - "node": ">=6.11.5" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/ts-loader/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "out/vsce" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "dependencies": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - } - }, - "node_modules/vscode-json-languageservice/node_modules/vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "dependencies": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "engines": { - "vscode": "^1.41.0" - } - }, - "node_modules/vscode-languageclient/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "dependencies": { - "vscode-languageserver-protocol": "^3.15.3" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "dependencies": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "node_modules/vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "dependencies": { - "tas-client": "0.1.45" - }, - "engines": { - "vscode": "^1.19.1" - } - }, - "node_modules/vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-cli/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/webpack-cli/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, - "node_modules/yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "requires": { - "tslib": "^2.0.0" - }, - "dependencies": { - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - } - } - }, - "@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==" - }, - "@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "requires": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - }, - "dependencies": { - "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 - } - } - }, - "@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "requires": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "requires": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "requires": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^4.28.5" - } - }, - "@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "requires": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "dependencies": { - "@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "requires": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "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 - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - } - }, - "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } - } - } - }, - "@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "requires": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - } - } - }, - "@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "requires": {} - }, - "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - } - }, - "@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "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" - } - } - } - }, - "@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "requires": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, - "@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "requires": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - }, - "dependencies": { - "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" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "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" - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.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" - } - }, - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "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" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true - } - } - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "requires": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "requires": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - } - }, - "@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - } - }, - "@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "requires": { - "fast-memoize": "^2.3.2" - } - }, - "@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "requires": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - } - }, - "@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "dependencies": { - "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" - } - } - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "requires": {} - }, - "@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "requires": {} - }, - "adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - } - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "requires": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - } - } - }, - "copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "requires": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "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" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.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" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true - }, - "dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "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 - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "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==" - }, - "eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "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" - } - }, - "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" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "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 - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.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" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.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" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "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" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "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" - } - } - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "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" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "requires": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.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": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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" - } - } - } - }, - "loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "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.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^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" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.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 - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "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" - } - }, - "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 - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "requires": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "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 - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "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" - } - } - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "requires": { - "require-at": "^1.0.6" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "requires": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "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 - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "requires": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - } - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "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" - }, - "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" - } - }, - "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 - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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 - } - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "requires": { - "parseley": "^0.7.0" - } - }, - "semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=" - }, - "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "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 - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.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" - } - }, - "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 - }, - "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 - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "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" - } - } - } - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "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 - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "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" - } - } - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } - } - }, - "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - } - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "requires": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - }, - "dependencies": { - "vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - } - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "requires": { - "vscode-languageserver-protocol": "^3.15.3" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "requires": { - "tas-client": "0.1.45" - } - }, - "vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - } - } - }, - "webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - } - } - }, - "webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - } - }, - "webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "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" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index b710e8ca1..cb3570684 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "displayName": "Azure Databases", "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", "engines": { - "vscode": "^1.66.0" + "vscode": "1.66.0" }, "galleryBanner": { "color": "#3c3c3c", @@ -1052,61 +1052,61 @@ "prepare": "husky install" }, "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.2", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.12", + "@types/fs-extra": "11.0.4", + "@types/gulp": "4.0.17", + "@types/mocha": "10.0.4", + "@types/mongodb": "4.0.6", + "@types/node": "20.9.0", + "@types/pg": "8.10.9", + "@types/vscode": "1.84.1", + "@typescript-eslint/eslint-plugin": "6.11.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.53.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2" }, "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.2.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" }, "extensionDependencies": [ "ms-vscode.azure-account", From 286a82d010eba7545e6538fc3c0e6033bd9a2c07 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Fri, 17 Nov 2023 03:23:37 +0200 Subject: [PATCH 15/33] squash! --- .github/CODEOWNERS | 1 - .github/workflows/bump-version-pr.yaml | 30 - .github/workflows/feature-request.yml | 43 - .github/workflows/info-needed-closer.yml | 27 - .github/workflows/locker.yml | 24 - package-lock.json | 21347 ---------------- src/AzureDBExperiences.ts | 118 - src/DatabasesFileSystem.ts | 77 - src/ParsedConnectionString.ts | 28 - src/azureAccountUtils.ts | 31 - .../api/DatabaseAccountTreeItemInternal.ts | 106 - src/commands/api/DatabaseTreeItemInternal.ts | 42 - src/commands/api/apiCache.ts | 46 - src/commands/api/findTreeItem.ts | 146 - src/commands/api/pickTreeItem.ts | 100 - src/commands/api/revealTreeItem.ts | 16 - .../DatabaseAccountDeleteStep.ts | 19 - .../IDeleteWizardContext.ts | 13 - .../deleteCosmosDBAccount.ts | 32 - .../deleteDatabaseAccount.ts | 37 - src/commands/importDocuments.ts | 163 - src/constants.ts | 136 - src/docdb/docDBConnectionStrings.ts | 42 - src/docdb/getCosmosClient.ts | 19 - src/docdb/registerDocDBCommands.ts | 104 - src/docdb/tree/DocDBAccountTreeItem.ts | 37 - src/docdb/tree/DocDBAccountTreeItemBase.ts | 95 - src/docdb/tree/DocDBCollectionTreeItem.ts | 92 - src/docdb/tree/DocDBDatabaseTreeItem.ts | 22 - src/docdb/tree/DocDBDatabaseTreeItemBase.ts | 161 - src/docdb/tree/DocDBDocumentTreeItem.ts | 133 - src/docdb/tree/DocDBDocumentsTreeItem.ts | 129 - .../tree/DocDBStoredProcedureTreeItem.ts | 76 - .../tree/DocDBStoredProceduresTreeItem.ts | 97 - src/docdb/tree/DocDBTreeItemBase.ts | 55 - src/docdb/tree/DocDBUtils.ts | 12 - src/docdb/tree/IDocDBTreeRoot.ts | 14 - src/extension.ts | 215 - src/extensionVariables.ts | 51 - src/getExtensionApi.ts | 31 - src/graph/gremlinEndpoints.ts | 47 - src/graph/registerGraphCommands.ts | 62 - src/graph/tree/GraphAccountTreeItem.ts | 45 - src/graph/tree/GraphCollectionTreeItem.ts | 87 - src/graph/tree/GraphDatabaseTreeItem.ts | 65 - src/graph/tree/GraphTreeItem.ts | 56 - src/mongo/MongoCommand.ts | 24 - src/mongo/MongoScrapbook.ts | 491 - src/mongo/MongoShell.ts | 187 - src/mongo/connectToMongoClient.ts | 49 - src/mongo/errorListeners.ts | 67 - src/mongo/grammar/mongo.tokens | 36 - src/mongo/grammar/mongoLexer.tokens | 36 - src/mongo/grammar/mongoLexer.ts | 247 - src/mongo/grammar/mongoListener.ts | 208 - src/mongo/grammar/mongoParser.ts | 1466 -- src/mongo/grammar/mongoVisitor.ts | 143 - src/mongo/grammar/visitors.ts | 83 - src/mongo/languageClient.ts | 58 - src/mongo/languageServer.ts | 31 - src/mongo/mongoConnectionStrings.ts | 104 - src/mongo/registerMongoCommands.ts | 223 - src/mongo/services/IConnectionParams.ts | 10 - src/mongo/services/MongoCodeLensProvider.ts | 75 - src/mongo/services/completionItemProvider.ts | 439 - src/mongo/services/languageService.ts | 90 - src/mongo/services/mongoScript.ts | 101 - src/mongo/services/schemaService.ts | 628 - src/mongo/setConnectedNode.ts | 13 - src/mongo/tree/IMongoTreeRoot.ts | 9 - src/mongo/tree/MongoAccountTreeItem.ts | 140 - src/mongo/tree/MongoCollectionTreeItem.ts | 320 - src/mongo/tree/MongoDatabaseTreeItem.ts | 258 - src/mongo/tree/MongoDocumentTreeItem.ts | 97 - .../abstract/AbstractPostgresClient.ts | 23 - src/postgres/abstract/models.ts | 55 - src/postgres/commands/checkAuthentication.ts | 36 - .../commands/configurePostgresFirewall.ts | 69 - .../commands/connectPostgresDatabase.ts | 39 - src/postgres/commands/copyConnectionString.ts | 36 - .../commands/createPostgresDatabase.ts | 26 - .../IPostgresQueryWizardContext.ts | 12 - .../IPostgresFunctionQueryWizardContext.ts | 10 - .../function/createPostgresFunctionQuery.ts | 23 - .../function/steps/FunctionQueryCreateStep.ts | 31 - .../FunctionQueryCustomReturnTypeStep.ts | 18 - .../function/steps/FunctionQueryNameStep.ts | 22 - .../steps/FunctionQueryReturnTypeStep.ts | 50 - .../runPostgresQueryWizard.ts | 23 - .../createPostgresStoredProcedureQuery.ts | 20 - .../steps/StoredProcedureQueryCreateStep.ts | 30 - .../steps/StoredProcedureQueryNameStep.ts | 22 - .../createPostgresQuery/validateIdentifier.ts | 113 - .../IPostgresServerWizardContext.ts | 24 - .../steps/PostgresServerConfirmPWStep.ts | 31 - .../steps/PostgresServerCreateStep.ts | 104 - .../steps/PostgresServerCredPWStep.ts | 53 - .../steps/PostgresServerCredUserStep.ts | 48 - .../steps/PostgresServerNameStep.ts | 60 - .../steps/PostgresServerSetCredentialsStep.ts | 46 - .../steps/PostgresServerSkuStep.ts | 250 - .../commands/deletePostgresDatabase.ts | 30 - .../commands/deletePostgresFunction.ts | 29 - src/postgres/commands/deletePostgresServer.ts | 22 - .../commands/deletePostgresStoredProcedure.ts | 29 - src/postgres/commands/deletePostgresTable.ts | 28 - .../commands/enterPostgresCredentials.ts | 85 - .../executePostgresQueryInDocument.ts | 65 - src/postgres/commands/openPostgresFunction.ts | 21 - .../commands/openPostgresStoredProcedure.ts | 21 - .../commands/registerPostgresCommands.ts | 82 - .../commands/setPostgresCredentials.ts | 32 - src/postgres/getClientConfig.ts | 172 - src/postgres/getPostgresProcedureQueryRows.ts | 58 - src/postgres/getTables.ts | 34 - src/postgres/postgresConnectionStrings.ts | 74 - src/postgres/postgresConstants.ts | 8 - src/postgres/runPostgresQuery.ts | 19 - .../services/PostgresCodeLensProvider.ts | 66 - src/postgres/showPostgresQuery.ts | 14 - src/postgres/tree/ClientConfigFactory.ts | 86 - src/postgres/tree/PostgresColumnTreeItem.ts | 33 - src/postgres/tree/PostgresDatabaseTreeItem.ts | 115 - src/postgres/tree/PostgresFunctionTreeItem.ts | 48 - .../tree/PostgresFunctionsTreeItem.ts | 46 - .../tree/PostgresResourcesTreeItemBase.ts | 27 - src/postgres/tree/PostgresServerTreeItem.ts | 252 - .../tree/PostgresStoredProcedureTreeItem.ts | 48 - .../tree/PostgresStoredProceduresTreeItem.ts | 46 - src/postgres/tree/PostgresTableTreeItem.ts | 56 - src/postgres/tree/PostgresTablesTreeItem.ts | 51 - src/resolver/AppResolver.ts | 71 - src/resolver/DatabaseWorkspaceProvider.ts | 33 - .../ResolvedDatabaseAccountResource.ts | 57 - src/resolver/ResolvedDocDBAccountResource.ts | 32 - src/resolver/ResolvedMongoAccountResource.ts | 20 - .../ResolvedPostgresServerResource.ts | 48 - src/table/tree/TableAccountTreeItem.ts | 39 - src/tree/AttachedAccountsTreeItem.ts | 420 - src/tree/AzureAccountTreeItemWithAttached.ts | 36 - src/tree/AzureDBAPIStep.ts | 76 - .../CosmosDBAccountCapacityStep.ts | 40 - .../CosmosDBAccountCreateStep.ts | 63 - .../CosmosDBAccountNameStep.ts | 49 - .../ICosmosDBWizardContext.ts | 19 - src/tree/IAzureDBWizardContext.ts | 14 - src/tree/SubscriptionTreeItem.ts | 158 - src/utils/InteractiveChildProcess.ts | 176 - src/utils/activityUtils.ts | 15 - src/utils/array.ts | 14 - src/utils/azureClients.ts | 24 - src/utils/azureUtils.ts | 14 - src/utils/cp.ts | 14 - src/utils/getIp.ts | 61 - src/utils/getSecretStorageKey.ts | 8 - src/utils/improveError.ts | 17 - src/utils/localize.ts | 8 - src/utils/nonNull.ts | 41 - src/utils/openUrl.ts | 13 - src/utils/randomUtils.ts | 17 - src/utils/settingUtils.ts | 62 - src/utils/timeout.ts | 51 - src/utils/vscodeUtils.ts | 103 - src/utils/workspacUtils.ts | 18 - src/utils/wrapError.ts | 24 - src/vscode-cosmosdb.api.d.ts | 96 - src/vscode-cosmosdbgraph.api.d.ts | 29 - test/.eslintrc.js | 6 - test/attachedAccountsTreeItem.test.ts | 27 - test/docDBConnectionStrings.test.ts | 61 - test/documentLabel.test.ts | 29 - test/global.test.ts | 20 - test/improveError.test.ts | 24 - test/index.ts | 55 - test/mongoConnectionStrings.test.ts | 165 - test/mongoGetCommand.test.ts | 1138 - test/mongoShell.test.ts | 288 - test/postgresConnectionStrings.test.ts | 30 - test/runTest.ts | 46 - test/runWithSetting.ts | 24 - test/test.code-workspace | 8 - test/timeout.test.ts | 120 - test/unit/DocDBUtils.test.ts | 16 - test/unit/getClientConfig.test.ts | 182 - test/util/getIp.test.ts | 45 - test/util/setEnvironmentVariables.test.ts | 36 - test/util/setEnvironmentVariables.ts | 35 - test/wrapError.test.ts | 53 - 188 files changed, 37321 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/bump-version-pr.yaml delete mode 100644 .github/workflows/feature-request.yml delete mode 100644 .github/workflows/info-needed-closer.yml delete mode 100644 .github/workflows/locker.yml delete mode 100644 package-lock.json delete mode 100644 src/AzureDBExperiences.ts delete mode 100644 src/DatabasesFileSystem.ts delete mode 100644 src/ParsedConnectionString.ts delete mode 100644 src/azureAccountUtils.ts delete mode 100644 src/commands/api/DatabaseAccountTreeItemInternal.ts delete mode 100644 src/commands/api/DatabaseTreeItemInternal.ts delete mode 100644 src/commands/api/apiCache.ts delete mode 100644 src/commands/api/findTreeItem.ts delete mode 100644 src/commands/api/pickTreeItem.ts delete mode 100644 src/commands/api/revealTreeItem.ts delete mode 100644 src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts delete mode 100644 src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts delete mode 100644 src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts delete mode 100644 src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts delete mode 100644 src/commands/importDocuments.ts delete mode 100644 src/constants.ts delete mode 100644 src/docdb/docDBConnectionStrings.ts delete mode 100644 src/docdb/getCosmosClient.ts delete mode 100644 src/docdb/registerDocDBCommands.ts delete mode 100644 src/docdb/tree/DocDBAccountTreeItem.ts delete mode 100644 src/docdb/tree/DocDBAccountTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBCollectionTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDatabaseTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDatabaseTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBDocumentTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDocumentsTreeItem.ts delete mode 100644 src/docdb/tree/DocDBStoredProcedureTreeItem.ts delete mode 100644 src/docdb/tree/DocDBStoredProceduresTreeItem.ts delete mode 100644 src/docdb/tree/DocDBTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBUtils.ts delete mode 100644 src/docdb/tree/IDocDBTreeRoot.ts delete mode 100644 src/extension.ts delete mode 100644 src/extensionVariables.ts delete mode 100644 src/getExtensionApi.ts delete mode 100644 src/graph/gremlinEndpoints.ts delete mode 100644 src/graph/registerGraphCommands.ts delete mode 100644 src/graph/tree/GraphAccountTreeItem.ts delete mode 100644 src/graph/tree/GraphCollectionTreeItem.ts delete mode 100644 src/graph/tree/GraphDatabaseTreeItem.ts delete mode 100644 src/graph/tree/GraphTreeItem.ts delete mode 100644 src/mongo/MongoCommand.ts delete mode 100644 src/mongo/MongoScrapbook.ts delete mode 100644 src/mongo/MongoShell.ts delete mode 100644 src/mongo/connectToMongoClient.ts delete mode 100644 src/mongo/errorListeners.ts delete mode 100644 src/mongo/grammar/mongo.tokens delete mode 100644 src/mongo/grammar/mongoLexer.tokens delete mode 100644 src/mongo/grammar/mongoLexer.ts delete mode 100644 src/mongo/grammar/mongoListener.ts delete mode 100644 src/mongo/grammar/mongoParser.ts delete mode 100644 src/mongo/grammar/mongoVisitor.ts delete mode 100644 src/mongo/grammar/visitors.ts delete mode 100644 src/mongo/languageClient.ts delete mode 100644 src/mongo/languageServer.ts delete mode 100644 src/mongo/mongoConnectionStrings.ts delete mode 100644 src/mongo/registerMongoCommands.ts delete mode 100644 src/mongo/services/IConnectionParams.ts delete mode 100644 src/mongo/services/MongoCodeLensProvider.ts delete mode 100644 src/mongo/services/completionItemProvider.ts delete mode 100644 src/mongo/services/languageService.ts delete mode 100644 src/mongo/services/mongoScript.ts delete mode 100644 src/mongo/services/schemaService.ts delete mode 100644 src/mongo/setConnectedNode.ts delete mode 100644 src/mongo/tree/IMongoTreeRoot.ts delete mode 100644 src/mongo/tree/MongoAccountTreeItem.ts delete mode 100644 src/mongo/tree/MongoCollectionTreeItem.ts delete mode 100644 src/mongo/tree/MongoDatabaseTreeItem.ts delete mode 100644 src/mongo/tree/MongoDocumentTreeItem.ts delete mode 100644 src/postgres/abstract/AbstractPostgresClient.ts delete mode 100644 src/postgres/abstract/models.ts delete mode 100644 src/postgres/commands/checkAuthentication.ts delete mode 100644 src/postgres/commands/configurePostgresFirewall.ts delete mode 100644 src/postgres/commands/connectPostgresDatabase.ts delete mode 100644 src/postgres/commands/copyConnectionString.ts delete mode 100644 src/postgres/commands/createPostgresDatabase.ts delete mode 100644 src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/validateIdentifier.ts delete mode 100644 src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts delete mode 100644 src/postgres/commands/deletePostgresDatabase.ts delete mode 100644 src/postgres/commands/deletePostgresFunction.ts delete mode 100644 src/postgres/commands/deletePostgresServer.ts delete mode 100644 src/postgres/commands/deletePostgresStoredProcedure.ts delete mode 100644 src/postgres/commands/deletePostgresTable.ts delete mode 100644 src/postgres/commands/enterPostgresCredentials.ts delete mode 100644 src/postgres/commands/executePostgresQueryInDocument.ts delete mode 100644 src/postgres/commands/openPostgresFunction.ts delete mode 100644 src/postgres/commands/openPostgresStoredProcedure.ts delete mode 100644 src/postgres/commands/registerPostgresCommands.ts delete mode 100644 src/postgres/commands/setPostgresCredentials.ts delete mode 100644 src/postgres/getClientConfig.ts delete mode 100644 src/postgres/getPostgresProcedureQueryRows.ts delete mode 100644 src/postgres/getTables.ts delete mode 100644 src/postgres/postgresConnectionStrings.ts delete mode 100644 src/postgres/postgresConstants.ts delete mode 100644 src/postgres/runPostgresQuery.ts delete mode 100644 src/postgres/services/PostgresCodeLensProvider.ts delete mode 100644 src/postgres/showPostgresQuery.ts delete mode 100644 src/postgres/tree/ClientConfigFactory.ts delete mode 100644 src/postgres/tree/PostgresColumnTreeItem.ts delete mode 100644 src/postgres/tree/PostgresDatabaseTreeItem.ts delete mode 100644 src/postgres/tree/PostgresFunctionTreeItem.ts delete mode 100644 src/postgres/tree/PostgresFunctionsTreeItem.ts delete mode 100644 src/postgres/tree/PostgresResourcesTreeItemBase.ts delete mode 100644 src/postgres/tree/PostgresServerTreeItem.ts delete mode 100644 src/postgres/tree/PostgresStoredProcedureTreeItem.ts delete mode 100644 src/postgres/tree/PostgresStoredProceduresTreeItem.ts delete mode 100644 src/postgres/tree/PostgresTableTreeItem.ts delete mode 100644 src/postgres/tree/PostgresTablesTreeItem.ts delete mode 100644 src/resolver/AppResolver.ts delete mode 100644 src/resolver/DatabaseWorkspaceProvider.ts delete mode 100644 src/resolver/ResolvedDatabaseAccountResource.ts delete mode 100644 src/resolver/ResolvedDocDBAccountResource.ts delete mode 100644 src/resolver/ResolvedMongoAccountResource.ts delete mode 100644 src/resolver/ResolvedPostgresServerResource.ts delete mode 100644 src/table/tree/TableAccountTreeItem.ts delete mode 100644 src/tree/AttachedAccountsTreeItem.ts delete mode 100644 src/tree/AzureAccountTreeItemWithAttached.ts delete mode 100644 src/tree/AzureDBAPIStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts delete mode 100644 src/tree/IAzureDBWizardContext.ts delete mode 100644 src/tree/SubscriptionTreeItem.ts delete mode 100644 src/utils/InteractiveChildProcess.ts delete mode 100644 src/utils/activityUtils.ts delete mode 100644 src/utils/array.ts delete mode 100644 src/utils/azureClients.ts delete mode 100644 src/utils/azureUtils.ts delete mode 100644 src/utils/cp.ts delete mode 100644 src/utils/getIp.ts delete mode 100644 src/utils/getSecretStorageKey.ts delete mode 100644 src/utils/improveError.ts delete mode 100644 src/utils/localize.ts delete mode 100644 src/utils/nonNull.ts delete mode 100644 src/utils/openUrl.ts delete mode 100644 src/utils/randomUtils.ts delete mode 100644 src/utils/settingUtils.ts delete mode 100644 src/utils/timeout.ts delete mode 100644 src/utils/vscodeUtils.ts delete mode 100644 src/utils/workspacUtils.ts delete mode 100644 src/utils/wrapError.ts delete mode 100644 src/vscode-cosmosdb.api.d.ts delete mode 100644 src/vscode-cosmosdbgraph.api.d.ts delete mode 100644 test/.eslintrc.js delete mode 100644 test/attachedAccountsTreeItem.test.ts delete mode 100644 test/docDBConnectionStrings.test.ts delete mode 100644 test/documentLabel.test.ts delete mode 100644 test/global.test.ts delete mode 100644 test/improveError.test.ts delete mode 100644 test/index.ts delete mode 100644 test/mongoConnectionStrings.test.ts delete mode 100644 test/mongoGetCommand.test.ts delete mode 100644 test/mongoShell.test.ts delete mode 100644 test/postgresConnectionStrings.test.ts delete mode 100644 test/runTest.ts delete mode 100644 test/runWithSetting.ts delete mode 100644 test/test.code-workspace delete mode 100644 test/timeout.test.ts delete mode 100644 test/unit/DocDBUtils.test.ts delete mode 100644 test/unit/getClientConfig.test.ts delete mode 100644 test/util/getIp.test.ts delete mode 100644 test/util/setEnvironmentVariables.test.ts delete mode 100644 test/util/setEnvironmentVariables.ts delete mode 100644 test/wrapError.test.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index f426a03c5..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @Microsoft/vscodeazuretoolsdev diff --git a/.github/workflows/bump-version-pr.yaml b/.github/workflows/bump-version-pr.yaml deleted file mode 100644 index dec36e0a9..000000000 --- a/.github/workflows/bump-version-pr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Bump version after release - -# Run when release is published, or manually triggered -on: - release: - types: [published] - workflow_dispatch: - -jobs: - bump: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Bump version - id: bump - uses: alexweininger/bump-prerelease-version@v0.1.1 - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - title: ${{ env.MESSAGE }} - body: Automatically created by ${{ env.RUN_LINK }} - commit-message: ${{ env.MESSAGE }} - branch: bot/bump-${{ steps.bump.outputs.new-version }} - base: main - author: GitHub - env: - RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - MESSAGE: Bump version after release diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml deleted file mode 100644 index 94c0c5144..000000000 --- a/.github/workflows/feature-request.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Feature Request Manager -on: - issues: - types: [milestoned] - schedule: - - cron: 15 5 * * * # 10:15pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: actions/checkout@v3 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - run: npm install --production --prefix ./actions - - name: Run Feature Request Manager - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: ./actions/feature-request - with: - token: ${{secrets.AZCODE_BOT_PAT}} - candidateMilestoneID: 28 - candidateMilestoneName: "Backlog Candidates" - backlogMilestoneID: 33 - featureRequestLabel: "feature" - upvotesRequired: 5 - numCommentsOverride: 10 - initComment: "This feature request is now a candidate for our backlog. The community has 240 days to upvote the issue. If it receives 5 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectComment: ":slightly_frowning_face: In the last 60 days, this issue has received less than 5 community upvotes and we closed it. Still a big Thank You to you for taking the time to create it! To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectLabel: "out of scope" - warnComment: "This issue has become stale and is at risk of being closed. The community has 60 days to upvote the issue. If it receives 5 upvotes we will keep it open and take another look. If not, we will close it. To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - labelsToExclude: "P0,P1" - acceptComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - warnDays: 60 - closeDays: 240 - milestoneDelaySeconds: 60 - diff --git a/.github/workflows/info-needed-closer.yml b/.github/workflows/info-needed-closer.yml deleted file mode 100644 index 9304007a4..000000000 --- a/.github/workflows/info-needed-closer.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Info Needed Closer -on: - schedule: - - cron: 30 5 * * * # 10:30pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Info Needed Closer - uses: ./actions/needs-more-info-closer - with: - token: ${{secrets.AZCODE_BOT_PAT}} - label: info-needed - closeDays: 14 - closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/azcodeissuereporting) guidelines.\n\nHappy Coding!" - pingDays: 80 - pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information." diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml deleted file mode 100644 index 050406703..000000000 --- a/.github/workflows/locker.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Locker -on: - schedule: - - cron: 0 5 * * * # 10:00pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Locker - uses: ./actions/locker - with: - token: ${{secrets.AZCODE_BOT_PAT}} - daysSinceClose: 45 - daysSinceUpdate: 7 diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e16bd2f53..000000000 --- a/package-lock.json +++ /dev/null @@ -1,21347 +0,0 @@ -{ - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "license": "SEE LICENSE IN LICENSE.md", - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "engines": { - "vscode": "^1.66.0" - } - }, - "node_modules/@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@azure/abort-controller/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "node_modules/@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-cosmosdb/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-subscriptions/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-auth/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-client/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-lro/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "dependencies": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-paging/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-tracing/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-util/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/cosmos/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/cosmos/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/logger/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "node_modules/@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - } - }, - "node_modules/@azure/ms-rest-js/node_modules/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, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "dependencies": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "dependencies": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - }, - "peerDependencies": { - "tslib": "*" - } - }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "node_modules/@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "dependencies": { - "@typescript-eslint/parser": "^4.28.5" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=4", - "eslint": ">=7", - "eslint-plugin-import": ">=2" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "dependencies": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "dependencies": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "bin": { - "vscode-sort-package-json": "scripts/sortPackageJson.mjs" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "dependencies": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - }, - "node_modules/@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "dependencies": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "node_modules/@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "dependencies": { - "@types/webpack": "*" - } - }, - "node_modules/@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "node_modules/@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "dependencies": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "node_modules/@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "dependencies": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - } - }, - "node_modules/@types/gulp/node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/gulp/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@types/gulp/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@types/gulp/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/gulp/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/@types/gulp/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/@types/gulp/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "node_modules/@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "dependencies": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "node_modules/@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "node_modules/@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "node_modules/@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/uglify-js/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "node_modules/@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "node_modules/@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "dependencies": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "node_modules/@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "node_modules/@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "dependencies": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/webpack/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "dependencies": { - "fast-memoize": "^2.3.2" - } - }, - "node_modules/@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "dependencies": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - }, - "engines": { - "vscode": "^1.60.0" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/@vscode/test-electron/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "engines": { - "node": ">= 0.6.15" - } - }, - "node_modules/adal-node/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "node_modules/antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true, - "bin": { - "antlr4ts": "antlr4ts" - } - }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "dependencies": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - }, - "engines": { - "node": ">=8.9.0" - }, - "peerDependencies": { - "webpack": "*" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "node_modules/copy-props/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "dependencies": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/copy-webpack-plugin/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/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, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true, - "engines": { - "node": ">0.4.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "dev": true - }, - "node_modules/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 - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/enquirer/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/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 - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-glob/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli/node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, - "engines": { - "node": ">=10.23.2" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "dependencies": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/indexable-array/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/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 - }, - "node_modules/log-symbols/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true, - "engines": { - "node": ">= 6.14.4" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "peerDependencies": { - "mocha": ">=2.2.5" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-junit-reporter/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha-junit-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - } - }, - "node_modules/mocha-multi-reporters/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/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 - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - }, - "peerDependenciesMeta": { - "aws4": { - "optional": true - }, - "bson-ext": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "mongodb-extjson": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "dependencies": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/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, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "dependencies": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dependencies": { - "split": "^1.0.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "dependencies": { - "parseley": "^0.7.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/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 - }, - "node_modules/slice-ansi/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-color/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/table/node_modules/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/tas-client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tmp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "dependencies": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "engines": { - "node": ">=6.11.5" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/ts-loader/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "out/vsce" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "dependencies": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - } - }, - "node_modules/vscode-json-languageservice/node_modules/vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "dependencies": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "engines": { - "vscode": "^1.41.0" - } - }, - "node_modules/vscode-languageclient/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "dependencies": { - "vscode-languageserver-protocol": "^3.15.3" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "dependencies": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "node_modules/vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "dependencies": { - "tas-client": "0.1.45" - }, - "engines": { - "vscode": "^1.19.1" - } - }, - "node_modules/vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-cli/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/webpack-cli/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, - "node_modules/yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "requires": { - "tslib": "^2.0.0" - }, - "dependencies": { - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - } - } - }, - "@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==" - }, - "@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "requires": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - }, - "dependencies": { - "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 - } - } - }, - "@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "requires": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "requires": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "requires": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^4.28.5" - } - }, - "@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "requires": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "dependencies": { - "@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "requires": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "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 - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - } - }, - "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } - } - } - }, - "@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "requires": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - } - } - }, - "@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "requires": {} - }, - "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - } - }, - "@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "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" - } - } - } - }, - "@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "requires": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, - "@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "requires": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - }, - "dependencies": { - "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" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "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" - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.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" - } - }, - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "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" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true - } - } - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "requires": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "requires": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - } - }, - "@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - } - }, - "@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "requires": { - "fast-memoize": "^2.3.2" - } - }, - "@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "requires": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - } - }, - "@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "dependencies": { - "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" - } - } - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "requires": {} - }, - "@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "requires": {} - }, - "adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - } - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "requires": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - } - } - }, - "copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "requires": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "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" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.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" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true - }, - "dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "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 - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "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==" - }, - "eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "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" - } - }, - "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" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "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 - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.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" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.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" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "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" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "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" - } - } - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "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" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "requires": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.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": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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" - } - } - } - }, - "loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "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.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^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" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.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 - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "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" - } - }, - "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 - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "requires": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "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 - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "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" - } - } - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "requires": { - "require-at": "^1.0.6" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "requires": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "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 - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "requires": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - } - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "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" - }, - "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" - } - }, - "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 - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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 - } - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "requires": { - "parseley": "^0.7.0" - } - }, - "semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=" - }, - "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "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 - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.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" - } - }, - "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 - }, - "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 - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "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" - } - } - } - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "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 - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "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" - } - } - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } - } - }, - "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - } - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "requires": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - }, - "dependencies": { - "vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - } - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "requires": { - "vscode-languageserver-protocol": "^3.15.3" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "requires": { - "tas-client": "0.1.45" - } - }, - "vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - } - } - }, - "webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - } - } - }, - "webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - } - }, - "webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "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" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/src/AzureDBExperiences.ts b/src/AzureDBExperiences.ts deleted file mode 100644 index be9765dc6..000000000 --- a/src/AzureDBExperiences.ts +++ /dev/null @@ -1,118 +0,0 @@ -/* ------------------------------------------------------------------------------------------ - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { nonNullProp } from './utils/nonNull'; - -export enum API { - MongoDB = 'MongoDB', - Graph = 'Graph', - Table = 'Table', - Core = 'Core', - PostgresSingle = 'PostgresSingle', - PostgresFlexible = 'PostgresFlexible' -} - -export enum DBAccountKind { - MongoDB = 'MongoDB', - GlobalDocumentDB = 'GlobalDocumentDB' -} - -export type CapabilityName = 'EnableGremlin' | 'EnableTable'; - -export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; - } - return info; -} - -export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { - - const experience: Experience | undefined = tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); - const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); - return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); - -} - -export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { - return GremlinExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; -} - -export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; - - longName: string; - shortName: string; - description?: string; - - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; - - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; -} - -export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } -} - -export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } -} - -export function getExperienceQuickPick(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; -} - -export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; -} - -// Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" -// Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; -export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; -export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; -export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; -const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; -const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; - -const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; -const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; -const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); diff --git a/src/DatabasesFileSystem.ts b/src/DatabasesFileSystem.ts deleted file mode 100644 index 93c2b4938..000000000 --- a/src/DatabasesFileSystem.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; -import { FileChangeType } from "vscode-languageclient"; -import { ext } from "./extensionVariables"; -import { localize } from "./utils/localize"; -import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; -import { getNodeEditorLabel } from "./utils/vscodeUtils"; - -export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; -} - -export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = 'azureDatabases'; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; - - public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { - const size: number = Buffer.byteLength(await node.getFileContent(context)); - return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; - } - - public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { - return Buffer.from(await node.getFileContent(context)); - } - - public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { - const showSavePromptKey: string = 'showSavePrompt'; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = 'cosmosDB'; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { - const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); - const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError('dontUpload'); - } - } - - await node.writeFileContent(context, content.toString()); - await node.refresh(context); - - const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); - ext.outputChannel.appendLog(updatedMessage); - } - - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } - - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } - - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } -} diff --git a/src/ParsedConnectionString.ts b/src/ParsedConnectionString.ts deleted file mode 100644 index 99654ef5a..000000000 --- a/src/ParsedConnectionString.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; - - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; - - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } - - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } - - public get fullId(): string { - return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; - } -} diff --git a/src/azureAccountUtils.ts b/src/azureAccountUtils.ts deleted file mode 100644 index 7f37da4cd..000000000 --- a/src/azureAccountUtils.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtServiceClientCredentials } from "@microsoft/vscode-azext-utils"; -import { getApiExport } from "./getExtensionApi"; - -const azureAccountExtensionId = "ms-vscode.azure-account"; - -type AzureSession = { - userId: string; -}; - -/** - * @returns The user session of the signed-in azure account. - */ -export async function getAzureAdUserSession(): Promise { - const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; -} - -/** - * Gets a function that can request an access token for a specified scope for the signed-in azure account. - */ -export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { - return async () => { - const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; - return getTokenResult?.token ?? ""; - }; -} diff --git a/src/commands/api/DatabaseAccountTreeItemInternal.ts b/src/commands/api/DatabaseAccountTreeItemInternal.ts deleted file mode 100644 index 89a8c1164..000000000 --- a/src/commands/api/DatabaseAccountTreeItemInternal.ts +++ /dev/null @@ -1,106 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { API } from '../../AzureDBExperiences'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; - -export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { - protected _parsedCS: ParsedConnectionString; - private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; - - constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } - - public get connectionString(): string { - return this._parsedCS.connectionString; - } - - public get hostName(): string { - return this._parsedCS.hostName; - } - - public get port(): string { - return this._parsedCS.port; - } - - public get azureData(): { accountName: string, accountId: string } | undefined { - if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), - accountId: this._accountNode.fullId - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId - }; - } - } - return undefined; - } - - public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey - }; - } else { - return undefined; - } - } - - public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password - }; - } else { - return undefined; - } - } - - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); - }); - } - - protected async getAccountNode(context: IActionContext): Promise { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { - - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); - } - - return this._accountNode; - } -} diff --git a/src/commands/api/DatabaseTreeItemInternal.ts b/src/commands/api/DatabaseTreeItemInternal.ts deleted file mode 100644 index 9d6b0d140..000000000 --- a/src/commands/api/DatabaseTreeItemInternal.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; - -export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; - - constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } - - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); - } - - await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); - }); - } -} diff --git a/src/commands/api/apiCache.ts b/src/commands/api/apiCache.ts deleted file mode 100644 index 30da342aa..000000000 --- a/src/commands/api/apiCache.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; - -/** - * This cache is used to speed up api calls from other extensions to the Cosmos DB extension - * For now, it only helps on a per-session basis - */ -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = new Map(); - -export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { - sessionCache.set(parsedCS.fullId, treeItem); -} - -export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); -} - -export function removeTreeItemFromCache(expected: ParsedConnectionString): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); - } else { - actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); - } - if (actual && (actual.accountId === expected.accountId)) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } -} diff --git a/src/commands/api/findTreeItem.ts b/src/commands/api/findTreeItem.ts deleted file mode 100644 index 088413e52..000000000 --- a/src/commands/api/findTreeItem.ts +++ /dev/null @@ -1,146 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -export async function findTreeItem(query: TreeItemQuery): Promise { - return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, 'connectionString'); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = await rootNode.getCachedChildren(context); - result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - }); -} - -async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); - } - if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); - } else { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); - } - - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); - } else { - return new DatabaseAccountTreeItemInternal(expected, dbAccount); - } - - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; -} diff --git a/src/commands/api/pickTreeItem.ts b/src/commands/api/pickTreeItem.ts deleted file mode 100644 index dc84ce55a..000000000 --- a/src/commands/api/pickTreeItem.ts +++ /dev/null @@ -1,100 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; -import { databaseAccountType } from '../../constants'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { localize } from '../../utils/localize'; -import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; -function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case 'Mongo': - return MongoDatabaseTreeItem.contextValue; - case 'SQL': - return DocDBDatabaseTreeItem.contextValue; - case 'Graph': - return GraphDatabaseTreeItem.contextValue; - case 'Postgres': - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } -} - - -export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { - return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case 'Database': - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType ? - pickTreeOptions.apiType.map(getDatabaseContextValue) : - databaseContextValues; - break; - case 'DatabaseAccount': - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); - } - - const pickedItem = await ext.rgApi.pickAppResource(context, options); - - let parsedCS: ParsedConnectionString; - let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; - let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); - } - - const result = databaseNode ? - new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : - new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - }); -} diff --git a/src/commands/api/revealTreeItem.ts b/src/commands/api/revealTreeItem.ts deleted file mode 100644 index d13589351..000000000 --- a/src/commands/api/revealTreeItem.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { ext } from "../../extensionVariables"; - -export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); - } - }); -} diff --git a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts deleted file mode 100644 index 1ef9ca645..000000000 --- a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; - -export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } - - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } -} diff --git a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts deleted file mode 100644 index 762beb96e..000000000 --- a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; - -export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; -} diff --git a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts deleted file mode 100644 index a90956b30..000000000 --- a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; -import { localize } from '../../utils/localize'; -import { IDeleteWizardContext } from './IDeleteWizardContext'; - -export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await deletePromise; - const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } else { - await deletePromise; - } -} diff --git a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts deleted file mode 100644 index 4792710d4..000000000 --- a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; -import { createActivityContext } from "../../utils/activityUtils"; -import { localize } from "../../utils/localize"; -import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; - - -export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()) - }); - - const title = wizardContext.deletePostgres ? - localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : - localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) - - const confirmationMessage = wizardContext.deletePostgres ? - localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : - localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); - - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()] - }); - - await wizard.prompt(); - await wizard.execute(); -} diff --git a/src/commands/importDocuments.ts b/src/commands/importDocuments.ts deleted file mode 100644 index bd4c83e3f..000000000 --- a/src/commands/importDocuments.ts +++ /dev/null @@ -1,163 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ItemDefinition } from '@azure/cosmos'; -import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { cosmosMongoFilter, sqlFilter } from '../constants'; -import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; -import { ext } from '../extensionVariables'; -import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { getRootPath } from '../utils/workspacUtils'; - -export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); - ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents..." - }, - async (progress) => { - uris = nonNullValue(uris, 'uris'); - collectionNode = nonNullValue(collectionNode, 'collectionNode'); - - progress.report({ increment: 20, message: "Parsing documents for errors" }); - const documents = await parseDocuments(uris); - progress.report({ increment: 30, message: "Parsed documents. Importing" }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo(collectionNode, documents); - } else { - result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); - - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); -} - -async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"] - } - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); - erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); - ext.outputChannel.show(); - throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); - } - for (const document of documents) { - const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; -} diff --git a/src/constants.ts b/src/constants.ts deleted file mode 100644 index 0e6a4a14e..000000000 --- a/src/constants.ts +++ /dev/null @@ -1,136 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export const isWindows: boolean = /^win/.test(process.platform); - -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; -import { ext } from './extensionVariables'; - -export namespace Links { - export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; -} - -export interface IThemedIconPath { - light: string; - dark: string; -} - -export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'light', iconName), - dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) - }; - assert(fs.existsSync(a.light)); - return a; -} - -export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), - dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) - }; - assert(fs.existsSync(a.light)); - return a; -} - -export function getResourcesPath(): string { - return ext.context.asAbsolutePath('resources'); -} - -export const doubleClickDebounceDelay = 500; //milliseconds - -export const defaultStoredProcedure = - `function sample(prefix) { - var collection = getContext().getCollection(); - - // Query documents and take 1st item. - var isAccepted = collection.queryDocuments( - collection.getSelfLink(), - 'SELECT * FROM root r', - function (err, feed, options) { - if (err) throw err; - - // Check the feed and if empty, set the body to 'no docs found', - // else take 1st element from feed - if (!feed || !feed.length) { - var response = getContext().getResponse(); - response.setBody('no docs found'); - } - - else { - var response = getContext().getResponse(); - var body = { prefix: prefix, feed: feed[0] }; - response.setBody(JSON.stringify(body)); - } - }); - - if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};` ; - -export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; - -// https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = 'test'; - -export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; -export const postgresLanguageId: string = 'postgres'; -export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = 'query'; -export const postgresDefaultPort = '5432'; -export const postgresDefaultDatabase = 'postgres'; -export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; - -export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; - -export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; - -export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag - } -}; - -export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; - -export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag - } -}; - -export const tableDefaultExperienceTag = 'Azure Table'; - -export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag - } -}; - -export const sqlDefaultExperienceTag = 'Core (SQL)'; - -export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag - } -}; - -export const postgresFlexibleFilter = { - type: 'Microsoft.DBforPostgreSQL/flexibleServers' -}; - -export const postgresSingleFilter = { - type: 'Microsoft.DBForPostgreSQL/servers' -}; diff --git a/src/docdb/docDBConnectionStrings.ts b/src/docdb/docDBConnectionStrings.ts deleted file mode 100644 index 946490d21..000000000 --- a/src/docdb/docDBConnectionStrings.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as url from 'url'; -import { ParsedConnectionString } from '../ParsedConnectionString'; -import { nonNullProp } from '../utils/nonNull'; - -export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); - const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); - const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); - if (!endpoint || !masterKey) { - throw new Error('Invalid Document DB connection string.'); - } - return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); -} - -function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; -} - -export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - public readonly documentEndpoint: string; - public readonly masterKey: string; - - constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; - - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, 'hostname'); - this.port = nonNullProp(parsedEndpoint, 'port'); - } -} diff --git a/src/docdb/getCosmosClient.ts b/src/docdb/getCosmosClient.ts deleted file mode 100644 index 3b285fc9c..000000000 --- a/src/docdb/getCosmosClient.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient } from "@azure/cosmos"; -import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; -import * as https from "https"; -import * as vscode from 'vscode'; -import { ext } from "../extensionVariables"; - -export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { - - const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; - return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); - -} diff --git a/src/docdb/registerDocDBCommands.ts b/src/docdb/registerDocDBCommands.ts deleted file mode 100644 index 5eb7545e4..000000000 --- a/src/docdb/registerDocDBCommands.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { commands } from "vscode"; -import { doubleClickDebounceDelay, sqlFilter } from "../constants"; -import { ext } from "../extensionVariables"; -import { DocDBAccountTreeItem } from "./tree/DocDBAccountTreeItem"; -import { DocDBCollectionTreeItem } from "./tree/DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItem } from "./tree/DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./tree/DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./tree/DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; - -export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openDocument", documentNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); - } - const childNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - - } - await node.deleteTreeItem(context); - }); -} - -export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); - await databaseNode.createChild(context); -} - -export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.createChild(context); -} - -export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - sqlFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/docdb/tree/DocDBAccountTreeItem.ts b/src/docdb/tree/DocDBAccountTreeItem.ts deleted file mode 100644 index 0cee7ed06..000000000 --- a/src/docdb/tree/DocDBAccountTreeItem.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; - -export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; - - public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } -} diff --git a/src/docdb/tree/DocDBAccountTreeItemBase.ts b/src/docdb/tree/DocDBAccountTreeItemBase.ts deleted file mode 100644 index da9eec6b7..000000000 --- a/src/docdb/tree/DocDBAccountTreeItemBase.ts +++ /dev/null @@ -1,95 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { rejectOnTimeout } from '../../utils/timeout'; -import { getCosmosClient } from '../getCosmosClient'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class provides common logic for DocumentDB, Graph, and Table accounts - * (DocumentDB is the base type for all Cosmos DB accounts) - */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; - - - constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) - }; - - this.valuesToMask.push(id, endpoint, masterKey); - } - - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public get isServerless(): boolean { - return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; - - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.databases.readAll(feedOptions); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: 'Database Name', - validateInput: validateDatabaseName, - stepName: 'createDatabase' - }); - - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ id: databaseName }); - return this.initChild(nonNullProp(database, 'resource')); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } -} - -function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; -} diff --git a/src/docdb/tree/DocDBCollectionTreeItem.ts b/src/docdb/tree/DocDBCollectionTreeItem.ts deleted file mode 100644 index 987bbe3b4..000000000 --- a/src/docdb/tree/DocDBCollectionTreeItem.ts +++ /dev/null @@ -1,92 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * Represents a DocumentDB collection - */ -export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - } -} diff --git a/src/docdb/tree/DocDBDatabaseTreeItem.ts b/src/docdb/tree/DocDBDatabaseTreeItem.ts deleted file mode 100644 index ee8c23694..000000000 --- a/src/docdb/tree/DocDBDatabaseTreeItem.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; - -export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Collection'; - - public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } - - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } -} diff --git a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts b/src/docdb/tree/DocDBDatabaseTreeItemBase.ts deleted file mode 100644 index aa7e8d779..000000000 --- a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ /dev/null @@ -1,161 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -const minThroughputFixed: number = 400; -const minThroughputPartitioned: number = 400; -const maxThroughput: number = 100000; -const throughputStepSize = 100; - -/** - * This class provides common logic for DocumentDB, Graph, and Table databases - * (DocumentDB is the base type for all Cosmos DB accounts) - */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public get id(): string { - return nonNullProp(this._database, 'id'); - } - - public get label(): string { - return nonNullProp(this._database, 'id'); - } - - public get link(): string { - return nonNullProp(this._database, '_self'); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.database(this._database.id).containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl(context: ICreateChildImplContext): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}` - }); - - const containerDefinition: ContainerDefinition = { - id: containerName - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey] - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !(containerDefinition.partitionKey); - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const throughput: number = Number(await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: 'throughputCapacity', - validateInput: (input: string) => validateThroughput(isFixed, input) - })); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, 'resource')); - } - - protected async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address/zipCode' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } -} - -function validateThroughput(isFixed: boolean, input: string): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const value = Number(input); - if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; -} - -function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; -} diff --git a/src/docdb/tree/DocDBDocumentTreeItem.ts b/src/docdb/tree/DocDBDocumentTreeItem.ts deleted file mode 100644 index 1505572d9..000000000 --- a/src/docdb/tree/DocDBDocumentTreeItem.ts +++ /dev/null @@ -1,133 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { sanitizeId } from './DocDBUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; - -/** - * Represents a Cosmos DB DocumentDB (SQL) document - */ -export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openDocument'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error(`The "_self" and "_etag" fields are required to update a document`); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; - const response = await this.getDocumentClient(client).replace(newData, options); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split('/'); - if (fields[0] === '') { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { //Partition Key exists, but this document doesn't have a value - return ''; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); - } -} diff --git a/src/docdb/tree/DocDBDocumentsTreeItem.ts b/src/docdb/tree/DocDBDocumentsTreeItem.ts deleted file mode 100644 index b8265444d..000000000 --- a/src/docdb/tree/DocDBDocumentsTreeItem.ts +++ /dev/null @@ -1,129 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; -import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class provides logic for DocumentDB collections - */ -export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = (await this.promptForPartitionKey(context, body)); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); - return nonNullProp(item, 'resource'); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split('/'); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { - const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: 'valueforParititionKey' - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { - //remove leading slash - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split('/'); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } -} diff --git a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts b/src/docdb/tree/DocDBStoredProcedureTreeItem.ts deleted file mode 100644 index 899eccd27..000000000 --- a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from "vscode"; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * Represents a Cosmos DB DocumentDB (SQL) stored procedure - */ -export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); - - constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openStoredProcedure'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get filePath(): string { - return this.label + '-cosmos-stored-procedure.js'; - } - - public get id(): string { - return this.procedure.id; - } - - public get label(): string { - return this.procedure.id; - } - - public get link(): string { - return this.procedure._self; - } - - public async getFileContent(): Promise { - return typeof this.procedure.body === 'string' ? this.procedure.body : ''; - - } - - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, 'resource'); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); - } -} diff --git a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts b/src/docdb/tree/DocDBStoredProceduresTreeItem.ts deleted file mode 100644 index 4c3ddfd1a..000000000 --- a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from "vscode"; -import { defaultStoredProcedure } from '../../constants'; -import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class represents the DocumentDB "Stored Procedures" node in the tree - */ -export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = (await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: 'createStoredProcedure', - validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) - })).trim(); - const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; - context.showCreatingTreeItem(spID); - const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, 'resource')); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize("nameLength", "Name has to be between 1 and 255 chars long"); - } - - if (/[/\\?#&]/.test(name)) { - return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); - } - - return undefined; - } -} diff --git a/src/docdb/tree/DocDBTreeItemBase.ts b/src/docdb/tree/DocDBTreeItemBase.ts deleted file mode 100644 index 4424603ae..000000000 --- a/src/docdb/tree/DocDBTreeItemBase.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * This class provides common iteration logic for DocumentDB accounts, databases, and collections - */ -export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; - - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public root: IDocDBTreeRoot; - - public abstract initChild(resource: T): AzExtTreeItem; - - public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); - } - - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); - - this._batchSize *= 2; - - return resourceArray.map((resource: T) => this.initChild(resource)); - } -} diff --git a/src/docdb/tree/DocDBUtils.ts b/src/docdb/tree/DocDBUtils.ts deleted file mode 100644 index 3d45cf950..000000000 --- a/src/docdb/tree/DocDBUtils.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/** - * Sanitize an the id of a DocDB tree item so it can be safely used in a query string. - * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding - */ -export function sanitizeId(id: string): string { - return id.replace(/\+/g, ' '); -} diff --git a/src/docdb/tree/IDocDBTreeRoot.ts b/src/docdb/tree/IDocDBTreeRoot.ts deleted file mode 100644 index 9179eb454..000000000 --- a/src/docdb/tree/IDocDBTreeRoot.ts +++ /dev/null @@ -1,14 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient } from "@azure/cosmos"; - -export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; -} diff --git a/src/extension.ts b/src/extension.ts deleted file mode 100644 index e68744157..000000000 --- a/src/extension.ts +++ /dev/null @@ -1,215 +0,0 @@ -/*-------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; -import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; -import { platform } from 'os'; -import * as vscode from 'vscode'; -import { DatabasesFileSystem } from './DatabasesFileSystem'; -import { findTreeItem } from './commands/api/findTreeItem'; -import { pickTreeItem } from './commands/api/pickTreeItem'; -import { revealTreeItem } from './commands/api/revealTreeItem'; -import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { importDocuments } from './commands/importDocuments'; -import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; -import { registerDocDBCommands } from './docdb/registerDocDBCommands'; -import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; -import { ext } from './extensionVariables'; -import { getResourceGroupsApi } from './getExtensionApi'; -import { registerGraphCommands } from './graph/registerGraphCommands'; -import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; -import { registerMongoCommands } from './mongo/registerMongoCommands'; -import { setConnectedNode } from './mongo/setConnectedNode'; -import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; -import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; -import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; -import { DatabaseResolver } from './resolver/AppResolver'; -import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; -import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; -import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; -import { localize } from './utils/localize'; - -const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; - -export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = 'true'; - activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); - - const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); - ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { - if (platform() !== 'win32') { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); - } - - await ext.attachedAccountsNode.attachEmulator(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh(actionContext, node); - } - }); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { - const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); - if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { - const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); - } - if (node instanceof MongoAccountTreeItem) { - if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments(actionContext, uris || [selectedNode], undefined); - } else { - await importDocuments(actionContext, undefined, selectedNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { - if (!node) { - node = await ext.rgApi.pickAppResource(actionContext, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); - registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); - registerEvent( - 'cosmosDB.onDidChangeConfiguration', - vscode.workspace.onDidChangeConfiguration, - async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { - actionContext.telemetry.properties.isActivationEvent = "true"; - actionContext.errorHandling.suppressDisplay = true; - if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { - await vscode.commands.executeCommand("azureDatabases.refresh"); - } - }); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); - registerReportIssueCommand('azureDatabases.reportIssue'); - }); - - return createApiProvider([{ - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: '1.2.0' - }]); -} - -// this method is called when your extension is deactivated -export function deactivateInternal(): void { - // NOOP -} - -export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { - if (!node) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); - } - - await SubscriptionTreeItem.createChild(context, node); -} - -export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await deleteDatabaseAccount(context, node, false) -} - -export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { - const message = 'The connection string has been copied to the clipboard'; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); -} diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts deleted file mode 100644 index 4a3fc2650..000000000 --- a/src/extensionVariables.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; -import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; -import { ExtensionContext, SecretStorage, TreeView } from "vscode"; -import { DatabasesFileSystem } from "./DatabasesFileSystem"; -import { MongoDBLanguageClient } from "./mongo/languageClient"; -import { MongoCodeLensProvider } from "./mongo/services/MongoCodeLensProvider"; -import { MongoDatabaseTreeItem } from "./mongo/tree/MongoDatabaseTreeItem"; -import { PostgresCodeLensProvider } from "./postgres/services/PostgresCodeLensProvider"; -import { PostgresDatabaseTreeItem } from "./postgres/tree/PostgresDatabaseTreeItem"; -import { AttachedAccountsTreeItem } from "./tree/AttachedAccountsTreeItem"; -import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWithAttached"; - -/** - * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts - */ -export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = 'azureDatabases'; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; - - export namespace settingsKeys { - export const mongoShellPath = 'mongo.shell.path'; - export const mongoShellArgs = 'mongo.shell.args'; - export const documentLabelFields = 'cosmosDB.documentLabelFields'; - export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; - export const mongoShellTimeout = 'mongo.shell.timeout'; - export const batchSize = 'azureDatabases.batchSize'; - - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } -} diff --git a/src/getExtensionApi.ts b/src/getExtensionApi.ts deleted file mode 100644 index bfd553e74..000000000 --- a/src/getExtensionApi.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { apiUtils } from "@microsoft/vscode-azext-utils"; -import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; -import { Extension, extensions } from "vscode"; -import { localize } from "./utils/localize"; - -export async function getApiExport(extensionId: string): Promise { - const extension: Extension | undefined = extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } - - return extension.exports; - } - - return undefined; -} - -export async function getResourceGroupsApi(): Promise { - const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); - if (rgApiProvider) { - return rgApiProvider.getApi('0.0.1'); - } else { - throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); - } -} diff --git a/src/graph/gremlinEndpoints.ts b/src/graph/gremlinEndpoints.ts deleted file mode 100644 index 1ef6b283d..000000000 --- a/src/graph/gremlinEndpoints.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { nonNullValue } from '../utils/nonNull'; -import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; - -export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; -} - -export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - - const documentSuffix = '.documents.azure.com'; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); - - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); - - return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } -} - -/** - * Parses a IGremlinPoint from a URL - * @param url An account URL such as 'https://.documents.azure.com:443/' - */ -function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; -} diff --git a/src/graph/registerGraphCommands.ts b/src/graph/registerGraphCommands.ts deleted file mode 100644 index 1746c638b..000000000 --- a/src/graph/registerGraphCommands.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; -import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; -import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./tree/GraphTreeItem"; - -export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph(context, GraphTreeItem.contextValue); - } - await node.showExplorer(context); - }, doubleClickDebounceDelay); -} - -export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); -} - -export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.createChild(context); -} - -async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosGremlinFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/graph/tree/GraphAccountTreeItem.ts b/src/graph/tree/GraphAccountTreeItem.ts deleted file mode 100644 index 7e1f561fa..000000000 --- a/src/graph/tree/GraphAccountTreeItem.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; - -export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } - - public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } -} diff --git a/src/graph/tree/GraphCollectionTreeItem.ts b/src/graph/tree/GraphCollectionTreeItem.ts deleted file mode 100644 index 63709d977..000000000 --- a/src/graph/tree/GraphCollectionTreeItem.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; - -export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - - } -} diff --git a/src/graph/tree/GraphDatabaseTreeItem.ts b/src/graph/tree/GraphDatabaseTreeItem.ts deleted file mode 100644 index 1c5332700..000000000 --- a/src/graph/tree/GraphDatabaseTreeItem.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; -import { GraphAccountTreeItem } from './GraphAccountTreeItem'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; - -export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Graph'; - - constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { - super(parent, database); - } - - public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } - - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } - - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } - - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - - } - - protected override async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } -} diff --git a/src/graph/tree/GraphTreeItem.ts b/src/graph/tree/GraphTreeItem.ts deleted file mode 100644 index 800fded5a..000000000 --- a/src/graph/tree/GraphTreeItem.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; - -const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; - -export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this.commandId = 'cosmosDB.openGraphExplorer'; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } -} diff --git a/src/mongo/MongoCommand.ts b/src/mongo/MongoCommand.ts deleted file mode 100644 index 79c33731f..000000000 --- a/src/mongo/MongoCommand.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { RecognitionException } from 'antlr4ts'; -import * as vscode from 'vscode'; - -export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; -} - -export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; -} diff --git a/src/mongo/MongoScrapbook.ts b/src/mongo/MongoScrapbook.ts deleted file mode 100644 index d5dfe6d00..000000000 --- a/src/mongo/MongoScrapbook.ts +++ /dev/null @@ -1,491 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ObjectID } from 'bson'; -import { Collection } from 'mongodb'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { filterType, findType } from '../utils/array'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { mongoLexer } from './grammar/mongoLexer'; -import * as mongoParser from './grammar/mongoParser'; -import { MongoVisitor } from './grammar/visitors'; -import { ErrorDescription, MongoCommand } from './MongoCommand'; -import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; -import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of (command.errors || [])) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; -} - -export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); -} - -export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); - return await executeCommand(context, command); -} - -function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } -} - -export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { - return getAllCommandsFromText(document.getText()); -} - -async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { - const label: string = 'Scrapbook-execute-all-results'; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } -} - -async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === 'find' && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, 'collection'); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); - await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === 'findOne') { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp(command, 'collection'); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); - if (!colNode) { - throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = 'Scrapbook-results'; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error('No MongoDB command found at the current cursor location.'); - } -} - -async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { - if (command.name === 'drop') { - await database.refresh(context); - } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); - if (collectionNode) { - await collectionNode.refresh(context); - } - } -} - -export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "" - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; -} - -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; -} - -class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop'); - this.commands.push({ - range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); - return {}; - } - } - - private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' - this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); - if (argumentContextArray.length > 1) { - this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); - return {}; - } - } - - private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { - if (!tokenText) { // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop'); - const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* - We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. - $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. - {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). - We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those - What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. - */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } - -} diff --git a/src/mongo/MongoShell.ts b/src/mongo/MongoShell.ts deleted file mode 100644 index b8f982ee8..000000000 --- a/src/mongo/MongoShell.ts +++ /dev/null @@ -1,187 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; -import { randomUtils } from '../utils/randomUtils'; -import { getBatchSizeSetting } from '../utils/workspacUtils'; -import { wrapError } from '../utils/wrapError'; - -const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; - -const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = '(More)'; - -const sentinelBase = 'EXECUTION COMPLETED'; -const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } - -export class MongoShell extends vscode.Disposable { - - constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { - super(() => this.dispose()); - } - - public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '' - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut(text => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); - - resolve(stdOutNoSentinel); - } - })); - disposables.push( - this._process.onStdErr(text => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - })); - disposables.push( - this._process.onError(error => { - reject(error); - })); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error("The process exited prematurely."); - } - - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } - finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } -} - -function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout( - () => { - reject(timeoutMessage); - }, - timeoutSeconds * 1000); - } -} - -function convertToSingleLine(script: string): string { - return script.split(os.EOL) - .map(line => line.trim()) - .join(''); - -} - -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} - -function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); -} diff --git a/src/mongo/connectToMongoClient.ts b/src/mongo/connectToMongoClient.ts deleted file mode 100644 index 88aa2df17..000000000 --- a/src/mongo/connectToMongoClient.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { MongoClient, MongoClientOptions } from 'mongodb'; -import { emulatorPassword, Links } from '../constants'; - -export async function connectToMongoClient(connectionString: string, appName: string): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string, name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - throw error; - } -} - -export class MongoConnectError extends Error { - constructor() { - super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); - } -} - -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); -} diff --git a/src/mongo/errorListeners.ts b/src/mongo/errorListeners.ts deleted file mode 100644 index ea582d544..000000000 --- a/src/mongo/errorListeners.ts +++ /dev/null @@ -1,67 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { Recognizer } from 'antlr4ts/Recognizer'; -import { Token } from 'antlr4ts/Token'; -import * as vscode from "vscode"; -import { ErrorDescription } from './MongoCommand'; - -export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { - - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } -} - -export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { - - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } -} diff --git a/src/mongo/grammar/mongo.tokens b/src/mongo/grammar/mongo.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/mongo/grammar/mongo.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/mongo/grammar/mongoLexer.tokens b/src/mongo/grammar/mongoLexer.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/mongo/grammar/mongoLexer.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/mongo/grammar/mongoLexer.ts b/src/mongo/grammar/mongoLexer.ts deleted file mode 100644 index 3b6cbbdd0..000000000 --- a/src/mongo/grammar/mongoLexer.ts +++ /dev/null @@ -1,247 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { RuleContext } from 'antlr4ts/RuleContext'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; - - - -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = [ - "DEFAULT_MODE" - ]; - - public static readonly ruleNames: string[] = [ - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", - "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", - "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", - "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", - "ExponentPart", "DecimalDigit", "WHITESPACE" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoLexer.ruleNames; } - - @Override - public get serializedATN(): string { return mongoLexer._serializedATN; } - - @Override - public get modeNames(): string[] { return mongoLexer.modeNames; } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text) - ; - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } - -} - diff --git a/src/mongo/grammar/mongoListener.ts b/src/mongo/grammar/mongoListener.ts deleted file mode 100644 index 43514f500..000000000 --- a/src/mongo/grammar/mongoListener.ts +++ /dev/null @@ -1,208 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - - -import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - - -/** - * This interface defines a complete listener for a parse tree produced by - * `mongoParser`. - */ -export interface mongoListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - enterMongoCommands?: (ctx: MongoCommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - exitMongoCommands?: (ctx: MongoCommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - enterCommands?: (ctx: CommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - exitCommands?: (ctx: CommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - enterCommand?: (ctx: CommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - exitCommand?: (ctx: CommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - enterEmptyCommand?: (ctx: EmptyCommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - exitEmptyCommand?: (ctx: EmptyCommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - enterCollection?: (ctx: CollectionContext) => void; - /** - * Exit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - exitCollection?: (ctx: CollectionContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - enterFunctionCall?: (ctx: FunctionCallContext) => void; - /** - * Exit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - exitFunctionCall?: (ctx: FunctionCallContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - enterArguments?: (ctx: ArgumentsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - exitArguments?: (ctx: ArgumentsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - enterArgument?: (ctx: ArgumentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - exitArgument?: (ctx: ArgumentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - enterObjectLiteral?: (ctx: ObjectLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - exitObjectLiteral?: (ctx: ObjectLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - enterArrayLiteral?: (ctx: ArrayLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - exitArrayLiteral?: (ctx: ArrayLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - enterElementList?: (ctx: ElementListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - exitElementList?: (ctx: ElementListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - enterPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - exitPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - enterPropertyValue?: (ctx: PropertyValueContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - exitPropertyValue?: (ctx: PropertyValueContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - enterLiteral?: (ctx: LiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - exitLiteral?: (ctx: LiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - enterPropertyName?: (ctx: PropertyNameContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - exitPropertyName?: (ctx: PropertyNameContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - enterComment?: (ctx: CommentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - exitComment?: (ctx: CommentContext) => void; -} - diff --git a/src/mongo/grammar/mongoParser.ts b/src/mongo/grammar/mongoParser.ts deleted file mode 100644 index c1d38f4d0..000000000 --- a/src/mongo/grammar/mongoParser.ts +++ /dev/null @@ -1,1466 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { TokenStream } from 'antlr4ts/TokenStream'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { mongoListener } from './mongoListener'; -import { mongoVisitor } from './mongoVisitor'; - - - - -export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", "commands", "command", "emptyCommand", "collection", - "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", - "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", - "literal", "propertyName", "comment" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoParser.ruleNames; } - - @Override - public get serializedATN(): string { return mongoParser._serializedATN; } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + - "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } - -} - -export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } -} - - -export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } -} - - -export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_command; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } -} - - -export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } -} - - -export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } -} - - -export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } -} - - -export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } -} - - -export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } -} - - -export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } -} - - -export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } - public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } - public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } -} - - -export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } - public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } -} - - diff --git a/src/mongo/grammar/mongoVisitor.ts b/src/mongo/grammar/mongoVisitor.ts deleted file mode 100644 index eb001a6e9..000000000 --- a/src/mongo/grammar/mongoVisitor.ts +++ /dev/null @@ -1,143 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - - -import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by `mongoParser`. - * - * @param The return type of the visit operation. Use `void` for - * operations with no return type. - */ -export interface mongoVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitMongoCommands?: (ctx: MongoCommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommands?: (ctx: CommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommand?: (ctx: CommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - * @return the visitor result - */ - visitEmptyCommand?: (ctx: EmptyCommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCollection?: (ctx: CollectionContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFunctionCall?: (ctx: FunctionCallContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArguments?: (ctx: ArgumentsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArgument?: (ctx: ArgumentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitObjectLiteral?: (ctx: ObjectLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArrayLiteral?: (ctx: ArrayLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitElementList?: (ctx: ElementListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyAssignment?: (ctx: PropertyAssignmentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyValue?: (ctx: PropertyValueContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - * @return the visitor result - */ - visitLiteral?: (ctx: LiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyName?: (ctx: PropertyNameContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitComment?: (ctx: CommentContext) => Result; -} - diff --git a/src/mongo/grammar/visitors.ts b/src/mongo/grammar/visitors.ts deleted file mode 100644 index e1ba1b63d..000000000 --- a/src/mongo/grammar/visitors.ts +++ /dev/null @@ -1,83 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; -import { mongoVisitor } from './mongoVisitor'; - -export class MongoVisitor implements mongoVisitor { - - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return null; - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } -} diff --git a/src/mongo/languageClient.ts b/src/mongo/languageClient.ts deleted file mode 100644 index e4bd4aefd..000000000 --- a/src/mongo/languageClient.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -import * as nls from 'vscode-nls'; -import { ext } from '../extensionVariables'; -import { IConnectionParams } from './services/IConnectionParams'; - -const localize = nls.loadMessageBundle(); - -export class MongoDBLanguageClient { - - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle ? - ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : - ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'mongo', scheme: 'file' }, - { language: 'mongo', scheme: 'untitled' } - ] - }; - - // Create the language client and start the client. - this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect(connectionString: string, databaseName: string): Promise { - await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } -} diff --git a/src/mongo/languageServer.ts b/src/mongo/languageServer.ts deleted file mode 100644 index d5d6ec484..000000000 --- a/src/mongo/languageServer.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from 'vscode-languageserver'; -import { LanguageService } from './services/languageService'; - -// -// -// -// HOW TO DEBUG THE LANGUAGE SERVER -// -// -// 1. Start the extension via F5 -// 2. Under vscode Debug pane, switch to "Attach to Language Server" -// 3. F5 -// -// -// - -// Create a connection for the server -const connection: IConnection = createConnection(); -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -console.log = connection.console.log.bind(connection.console); -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -console.error = connection.console.error.bind(connection.console); - -new LanguageService(connection); - -// Listen on the connection -connection.listen(); diff --git a/src/mongo/mongoConnectionStrings.ts b/src/mongo/mongoConnectionStrings.ts deleted file mode 100644 index 5f73db484..000000000 --- a/src/mongo/mongoConnectionStrings.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import { testDb } from "../constants"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullValue } from "../utils/nonNull"; -import { connectToMongoClient } from "./connectToMongoClient"; - -// Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): -// mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] -// Some example connection strings: -// mongodb://dbuser:dbpassword@dbname.mlab.com:14118 -// mongodb+srv://db1.example.net:27017,db2.example.net:2500/?replicaSet=test -// mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/database?ssh=true -// Regex splits into three parts: -// Full match -// mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] -// [database] - -const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; -const parseDatabaseName = '\/?([^/?]+)?'; -const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); - -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } - - return undefined; -} - -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } -} - -export async function parseMongoConnectionString(connectionString: string): Promise { - - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; - - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - - return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); -} - -export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } -} - -/** - * Encodes the username and password in the given Mongo DB connection string. - */ -export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } - - return connectionString; -} diff --git a/src/mongo/registerMongoCommands.ts b/src/mongo/registerMongoCommands.ts deleted file mode 100644 index 2dc36477a..000000000 --- a/src/mongo/registerMongoCommands.ts +++ /dev/null @@ -1,223 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { Experience, MongoExperience } from '../AzureDBExperiences'; -import { cosmosMongoFilter } from "../constants"; -import { ext } from "../extensionVariables"; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { MongoConnectError } from './connectToMongoClient'; -import { MongoDBLanguageClient } from "./languageClient"; -import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; -import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; -import { setConnectedNode } from "./setConnectedNode"; -import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; -import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; - -const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; -let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = 'mongo'; - -export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); - } - - const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); - if (oldNode) { - await oldNode.refresh(context); - } - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); - registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - }); -} - -async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); -} - -function launchMongoShell(): void { - const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); - terminal.sendText(`mongo`); - terminal.show(); -} - -function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }); - - // Update errors when document opened/changed - registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); -} - -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } -} - -export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); - - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); -} - -export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); -} - -export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } -} - -export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/mongo/services/IConnectionParams.ts b/src/mongo/services/IConnectionParams.ts deleted file mode 100644 index eec39e4cf..000000000 --- a/src/mongo/services/IConnectionParams.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; -} diff --git a/src/mongo/services/MongoCodeLensProvider.ts b/src/mongo/services/MongoCodeLensProvider.ts deleted file mode 100644 index 3407c50dd..000000000 --- a/src/mongo/services/MongoCodeLensProvider.ts +++ /dev/null @@ -1,75 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; - -export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; - - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } - - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } - - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; - - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; - - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized ? - 'Initializing...' : - isConnected ? - `Connected to ${database}` : - `Connect to a database`, - command: isInitialized && 'cosmosDB.connectMongoDB' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); - - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: 'cosmosDB.executeAllMongoCommands' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); - - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: 'cosmosDB.executeMongoCommand', - arguments: [cmd.range.start] - }, - range: cmd.range - }); - } - } - - return lenses; - }); - } -} diff --git a/src/mongo/services/completionItemProvider.ts b/src/mongo/services/completionItemProvider.ts deleted file mode 100644 index cba51890c..000000000 --- a/src/mongo/services/completionItemProvider.ts +++ /dev/null @@ -1,439 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-non-null-assertion */ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) - .then(list => { - return list!.items.map(item => { - const startPositionOffset = document.offsetAt(item.textEdit!.range.start); - const endPositionOffset = document.offsetAt(item.textEdit!.range.end); - item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range - }, - kind: CompletionItemKind.Keyword, - label: 'db' - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range) - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then(collections => { - return collections.map(collection => ({ - textEdit: { - newText: collection.collectionName, - range - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}` - })); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range) - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}` - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } - -} diff --git a/src/mongo/services/languageService.ts b/src/mongo/services/languageService.ts deleted file mode 100644 index 83b1b594e..000000000 --- a/src/mongo/services/languageService.ts +++ /dev/null @@ -1,90 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) - -import { Db } from 'mongodb'; -import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; -import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; - -export class LanguageService { - - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] } - } - }; - }); - - connection.onCompletion(textDocumentPosition => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) - .then(account => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db) - .then(schemas => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: uri => this.schemaService.resolveSchema(uri), - contributions: [] - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas - }); - } -} diff --git a/src/mongo/services/mongoScript.ts b/src/mongo/services/mongoScript.ts deleted file mode 100644 index 8d4c85398..000000000 --- a/src/mongo/services/mongoScript.ts +++ /dev/null @@ -1,101 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, Position } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { SchemaService } from './schemaService'; - -export class MongoScriptDocumentManager { - - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - } - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } -} - -export class MongoScriptDocument { - - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } - - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); - - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); - } - return Promise.resolve([]); - } -} - -class NodeFinder extends MongoVisitor { - - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; - const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; - const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; - const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; - - if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } -} diff --git a/src/mongo/services/schemaService.ts b/src/mongo/services/schemaService.ts deleted file mode 100644 index cf70e8cde..000000000 --- a/src/mongo/services/schemaService.ts +++ /dev/null @@ -1,628 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ - -import { Cursor, Db } from 'mongodb'; -import { SchemaConfiguration } from 'vscode-json-languageservice'; -// eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; - -export class SchemaService { - - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections() - .then(collections => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push(...[{ - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)] - }, { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)] - }]); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {} - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - for (const property of Object.keys(document)) { - if (!parent && - ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'] - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' - }, - $language: { - type: 'string', - description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' - }, - $caseSensitive: { - type: 'boolean', - description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` - } - }, - required: ['$search'] - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate' - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri - } - }; - schema.properties!.$and = { - type: 'array', - description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri - } - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri - } - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {} - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value' - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value' - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value' - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value' - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value' - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value' - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array' - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array' - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field' - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type' - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0] - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression' - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type' - }, - coordinates: { - type: 'array' - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string' - }, - properties: { - type: 'object' - } - } - } - } - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array' - }, - $polygon: { - type: 'array' - }, - $center: { - type: 'array' - }, - $centerSphere: { - type: 'array' - } - } - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema - } - }; - expressionSchema.properties.$near = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query' - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size' - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties } - }; - schema.properties!.$elemMatch = { - type: 'object' - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view' - } - } - - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri - } - } - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'] - } - }, - additionalProperties: { - type: 'object' - } - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' - } - } - }); - return { - type: 'object', - oneOf: schemas - }; - } - - private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then(hasNext => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then(doc => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } - -} diff --git a/src/mongo/setConnectedNode.ts b/src/mongo/setConnectedNode.ts deleted file mode 100644 index f5680d09d..000000000 --- a/src/mongo/setConnectedNode.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from "../extensionVariables"; -import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; - -export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); -} diff --git a/src/mongo/tree/IMongoTreeRoot.ts b/src/mongo/tree/IMongoTreeRoot.ts deleted file mode 100644 index d9b68980d..000000000 --- a/src/mongo/tree/IMongoTreeRoot.ts +++ /dev/null @@ -1,9 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface IMongoTreeRoot { - isEmulator: boolean | undefined; -} diff --git a/src/mongo/tree/MongoAccountTreeItem.ts b/src/mongo/tree/MongoAccountTreeItem.ts deleted file mode 100644 index baa870c23..000000000 --- a/src/mongo/tree/MongoAccountTreeItem.ts +++ /dev/null @@ -1,140 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; -import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; - -export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error('Missing connection string'); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); - - const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [{ - name: databaseInConnectionString, - empty: false - }]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); - databases = result.databases; - } - return databases - .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty - .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } - finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createMongoDatabase', - validateInput: validateDatabaseName - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } -} - -export function validateDatabaseName(database: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return "Database name cannot contain these characters - `/\\. \"$#?=`"; - } - return undefined; -} - -export interface IDatabaseInfo { - name?: string; - empty?: boolean; -} diff --git a/src/mongo/tree/MongoCollectionTreeItem.ts b/src/mongo/tree/MongoCollectionTreeItem.ts deleted file mode 100644 index eca0c8d32..000000000 --- a/src/mongo/tree/MongoCollectionTreeItem.ts +++ /dev/null @@ -1,320 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullValue } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { MongoCommand } from '../MongoCommand'; -import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; -type MongoDocument = { _id: string }; -class FunctionDescriptor { - public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { - } -} - -export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, '_id'), - upsert: false - } - }; - }); - - const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = await this.getCachedChildren(context); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(children.map(c => c.document), null, 2); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get filePath(): string { - return this.label + '-cosmos-collection.json'; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { - const documentNodes = await this.getCachedChildren(context); - for (const doc of docs) { - const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection.find(this._query).batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - 'invalidMongoDocument', - doc => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; - - const functions = { - drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), - count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), - findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), - insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), - insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), - insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), - deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), - deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), - remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error(`Too few arguments passed to command ${command.name}.`); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error(`Too many arguments passed to command ${command.name}`); - } - if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number, name?: string } = e; - const NamespaceNotFoundCode = 26; - if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne(query?: Object, fieldsOption?: Object): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, '\t'); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error("The insert command requires at least one argument"); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count(query?: Object[], options?: MongoCountPreferences): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, '\t'); - } -} - -function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title - }, - (_progress) => { - return promise; - }); -} - -function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } -} diff --git a/src/mongo/tree/MongoDatabaseTreeItem.ts b/src/mongo/tree/MongoDatabaseTreeItem.ts deleted file mode 100644 index 73a7c6a22..000000000 --- a/src/mongo/tree/MongoDatabaseTreeItem.ts +++ /dev/null @@ -1,258 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import { Collection, Db, DbCollectionOptions } from 'mongodb'; -import * as path from 'path'; -import * as process from 'process'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { MongoCommand } from '../MongoCommand'; -import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; -import { MongoShell } from '../MongoShell'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoAccountTreeItem } from './MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; -const executingInShellMsg = "Executing command in Mongo shell"; - -export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map(collection => new MongoCollectionTreeItem(this, collection)); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: 'createMongoCollection', - validateInput: validateMongoCollectionName - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); - return accountConnection.db(this.databaseName); - } - - public async executeCommand(command: MongoCommand, context: IActionContext): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); - const result = await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - - } - - if (command.name === 'createCollection') { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); - } else { - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - } - } - - public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection(collectionName, options); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); - - if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); - return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); - } - - private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongo', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongo'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; - const browse: vscode.MessageItem = { title: 'Open installation page' }; - const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; - const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; - const tryAgain: vscode.MessageItem = { title: 'Try again' }; - const response2 = await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } -} - -export function validateMongoCollectionName(collectionName: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; -} - -function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title - }, - (_progress) => { - return promise; - }); -} - -export function stripQuotes(term: string): string { - if ((term.startsWith('\'') && term.endsWith('\'')) - || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; -} diff --git a/src/mongo/tree/MongoDocumentTreeItem.ts b/src/mongo/tree/MongoDocumentTreeItem.ts deleted file mode 100644 index ad44e43c3..000000000 --- a/src/mongo/tree/MongoDocumentTreeItem.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -export interface IMongoDocument { - _id: string | ObjectID; - - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; -} - -export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private _label: string; - - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = 'cosmosDB.openDocument'; - ext.fileSystem.fireChangedEvent(this); - } - - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } - - public get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public static async update(collection: Collection, newDocument: IMongoDocument): Promise { - if (!newDocument._id) { - throw new Error(`The "_id" field is required to update a document.`); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); - if (result.modifiedCount !== 1) { - throw new Error(`Failed to update document with _id '${newDocument._id}'.`); - } - return newDocument; - } - - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); - const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error(`Failed to delete document with _id '${this.document._id}'.`); - } - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); - } -} diff --git a/src/postgres/abstract/AbstractPostgresClient.ts b/src/postgres/abstract/AbstractPostgresClient.ts deleted file mode 100644 index c1fa29c4f..000000000 --- a/src/postgres/abstract/AbstractPostgresClient.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; -import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; -import { PostgresServerType } from "./models"; - -export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; - -export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context) - case PostgresServerType.Single: - return await createPostgreSQLClient(context) - default: - throw new Error("Service not implemented."); - } -} diff --git a/src/postgres/abstract/models.ts b/src/postgres/abstract/models.ts deleted file mode 100644 index 6bdadf16a..000000000 --- a/src/postgres/abstract/models.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; - -export enum PostgresServerType { - Flexible = 'Flexible', - Single = 'Single' -} - -export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } - -export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; - -/** - * Billing information related properties of a server. - */ -export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; -} - -export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; -} - -export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; - -export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; diff --git a/src/postgres/commands/checkAuthentication.ts b/src/postgres/commands/checkAuthentication.ts deleted file mode 100644 index 6799d060c..000000000 --- a/src/postgres/commands/checkAuthentication.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { invalidCredentialsErrorType } from "../postgresConstants"; -import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { configurePostgresFirewall } from "./configurePostgresFirewall"; -import { enterPostgresCredentials } from "./enterPostgresCredentials"; - -export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); - - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; -} diff --git a/src/postgres/commands/configurePostgresFirewall.ts b/src/postgres/commands/configurePostgresFirewall.ts deleted file mode 100644 index 52a378fca..000000000 --- a/src/postgres/commands/configurePostgresFirewall.ts +++ /dev/null @@ -1,69 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { getPublicIpv4 } from "../../utils/getIp"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; - -export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), - { - modal: true, - stepName: 'postgresAddFirewallRule' - }, - { title: DialogResponses.yes.title } - ); - - await setFirewallRule(context, treeItem, ip); -} - -export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { - - const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); - const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); - const serverName: string = nonNullProp(treeItem, 'azureName'); - - const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip - }; - - const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); - }); - const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); -} - -export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); -} diff --git a/src/postgres/commands/connectPostgresDatabase.ts b/src/postgres/commands/connectPostgresDatabase.ts deleted file mode 100644 index 6996f7d03..000000000 --- a/src/postgres/commands/connectPostgresDatabase.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from 'vscode'; -import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from "../../extensionVariables"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; - -export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); - - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } -} diff --git a/src/postgres/commands/copyConnectionString.ts b/src/postgres/commands/copyConnectionString.ts deleted file mode 100644 index 716bbd5b6..000000000 --- a/src/postgres/commands/copyConnectionString.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; - -export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); - } else { - connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); - } - - await vscode.env.clipboard.writeText(connectionString); - const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); - void vscode.window.showInformationMessage(message); -} diff --git a/src/postgres/commands/createPostgresDatabase.ts b/src/postgres/commands/createPostgresDatabase.ts deleted file mode 100644 index 6c096a52b..000000000 --- a/src/postgres/commands/createPostgresDatabase.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -import { connectPostgresDatabase } from './connectPostgresDatabase'; - -export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); -} diff --git a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts deleted file mode 100644 index 81d54b9af..000000000 --- a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ /dev/null @@ -1,12 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; - -export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; -} diff --git a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts deleted file mode 100644 index 27b32993c..000000000 --- a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; - -export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { - returnType?: string; -} diff --git a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts deleted file mode 100644 index 8c4df098b..000000000 --- a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, IActionContext } from "@microsoft/vscode-azext-utils"; -import { PostgresFunctionsTreeItem } from "../../../tree/PostgresFunctionsTreeItem"; -import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; -import { IPostgresFunctionQueryWizardContext } from "./IPostgresFunctionQueryWizardContext"; -import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; -import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; -import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; - -export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], - executeSteps: [new FunctionQueryCreateStep()], - title: 'Create PostgreSQL Function Query' - }); - - await runPostgresQueryWizard(wizard, wizardContext, treeItem); -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts deleted file mode 100644 index 9356882d9..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "../../../../../utils/nonNull"; -import { wrapArgInQuotes } from "../../../../runPostgresQuery"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IPostgresFunctionQueryWizardContext): Promise { - context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); - } - - public shouldExecute(): boolean { - return true; - } -} - -const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) - RETURNS ${returnType} - LANGUAGE plpgsql -AS $function$ - BEGIN - /* function body */ - END; -$function$ -`; diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts deleted file mode 100644 index cfacc0f64..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts deleted file mode 100644 index 36d798074..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { validateIdentifier } from "../../validateIdentifier"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideFunctionName', 'Provide function name'), - validateInput: validateIdentifier - })).trim(); - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts deleted file mode 100644 index 63f703793..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ /dev/null @@ -1,50 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; -import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; - -export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); - returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); - - context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize('selectReturnType', 'Select return type') - })).data; - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } - - public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { - return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } -} - -// A subset of return types available on pgAdmin -const returnTypes: string[] = [ - 'bigint', - 'bigint[]', - 'boolean', - 'boolean[]', - 'character', - 'character[]', - 'date', - 'date[]', - 'integer', - 'integer[]', - 'json', - 'json[]', - 'oid', - 'oid[]', - 'smallint', - 'smallint[]', - 'text', - 'void' -]; diff --git a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts deleted file mode 100644 index 925695e56..000000000 --- a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; -import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from '../../../utils/vscodeUtils'; -import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; -import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; -import { connectPostgresDatabase } from "../connectPostgresDatabase"; -import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; - -export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); - - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } -} diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts deleted file mode 100644 index f1ddbe51b..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, IActionContext } from "@microsoft/vscode-azext-utils"; -import { PostgresStoredProceduresTreeItem } from "../../../tree/PostgresStoredProceduresTreeItem"; -import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; -import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; -import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; - -export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: 'Create PostgreSQL Stored Procedure Query' - }); - - await runPostgresQueryWizard(wizard, context, treeItem); -} diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts deleted file mode 100644 index 2cf3ef916..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "../../../../../utils/nonNull"; -import { wrapArgInQuotes } from "../../../../runPostgresQuery"; -import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; - -export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); - } - - public shouldExecute(): boolean { - return true; - } -} - -const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) - LANGUAGE plpgsql -AS $$ - BEGIN - /* stored procedure body */ - END; -$$ -`; diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts deleted file mode 100644 index bf9a00392..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; -import { validateIdentifier } from "../../validateIdentifier"; - -export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), - validateInput: validateIdentifier - })).trim(); - } - - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } -} diff --git a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts b/src/postgres/commands/createPostgresQuery/validateIdentifier.ts deleted file mode 100644 index 9339f6796..000000000 --- a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ /dev/null @@ -1,113 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { localize } from "../../../utils/localize"; - -export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); - - const min = 1; - const max = 63; - - if (identifier.length < min || identifier.length > max) { - return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } - - if (!identifier[0].match(/[a-z_]/i)) { - return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); - } - - if (identifier.match(/[^a-z_\d$]/i)) { - return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); - } - - if (reservedWords.has(identifier.toLowerCase())) { - return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); - } - - return undefined; -} - -// Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html -const reservedWords: Set = new Set([ - 'all', - 'analyse', - 'analyze', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'asymmetric', - 'both', - 'case', - 'cast', - 'check', - 'collate', - 'column', - 'constraint', - 'create', - 'current_catalog', - 'current_date', - 'current_role', - 'current_time', - 'current_timestamp', - 'current_user', - 'default', - 'deferrable', - 'desc', - 'distinct', - 'do', - 'else', - 'end', - 'except', - 'false', - 'fetch', - 'for', - 'foreign', - 'from', - 'grant', - 'group', - 'having', - 'in', - 'initially', - 'intersect', - 'into', - 'lateral', - 'leading', - 'limit', - 'localtime', - 'localtimestamp', - 'not', - 'null', - 'offset', - 'on', - 'only', - 'or', - 'order', - 'placing', - 'primary', - 'references', - 'returning', - 'select', - 'session_user', - 'some', - 'symmetric', - 'table', - 'then', - 'to', - 'trailing', - 'true', - 'union', - 'unique', - 'user', - 'using', - 'variadic', - 'when', - 'where', - 'window', - 'with' -]); diff --git a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts deleted file mode 100644 index 390c1cf42..000000000 --- a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; - -export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; - - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts deleted file mode 100644 index 2f07d8203..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; - -export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize('confirmPW', 'Confirm your password'); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) - }); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } - - private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { - if (passphrase !== context.adminPassword) { - return localize('pwMatch', 'The passwords must match.'); - } - - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts deleted file mode 100644 index f73ce810d..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; -import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; -import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; - - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - - const locationName: string = (await LocationListStep.getLocation(context)).name; - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); - const newServerName = nonNullProp(context, 'newServerName'); - const password: string = nonNullProp(context, 'adminPassword'); - - return await callWithMaskHandling( - async () => { - const serverType = nonNullProp(context, 'serverType'); - const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); - - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, 'sku'), - administratorLogin: nonNullProp(context, 'shortUserName'), - administratorLoginPassword: password, - size: parseInt(size) - }; - - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); - context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); - context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, - password); - } - - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } - - - private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier - }, - } - } - - private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size - } - } - } - } - -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts deleted file mode 100644 index c48d40c37..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); - -export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, 'shortUserName'); - context.adminPassword = (await context.ui.showInputBox({ - placeHolder: localize('pwPlaceholder', 'Administrator Password'), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => validatePassword(user, password), - })); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } -} - -async function validatePassword(username: string, password: string): Promise { - password = password ? password : ''; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map(substring => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); - } else { - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts deleted file mode 100644 index 7b4890d07..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = (await context.ui.showInputBox({ - placeHolder: localize('usernamePlaceholder', 'Administrator Username'), - validateInput: validateUser, - })).trim(); - const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; - context.longUserName = context.shortUserName + usernameSuffix; - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } -} - -async function validateUser(username: string): Promise { - username = username ? username.trim() : ''; - - const min = 1; - const max = 63; - - const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; - - if (username.length < min || username.length > max) { - return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); - } else if (username.match(/^[0-9]+/)) { - return localize('usernameBeginningMatch', 'The name cannot start with a number.'); - } else if (username.toLowerCase().startsWith('pg_')) { - return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map(d => `"${d}"`).join(', '); - return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); - } else { - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts deleted file mode 100644 index 1af03f5c7..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ /dev/null @@ -1,60 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; -import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerNameStep extends AzureNameStep { - - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: localize('serverNamePlaceholder', 'Server name'), - prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), - validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} - -async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { - name = name ? name.trim() : ''; - - const min = 3; - const max = 63; - - if (name.length < min || name.length > max) { - return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } else if (!(/^[a-z0-9-]+$/).test(name)) { - return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); - } else if (name.startsWith('-') || name.endsWith('-')) { - return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); - } - const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); - - if (!availability.nameAvailable) { - return availability.message ? - availability.message : - localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); - } - - return undefined; - -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts deleted file mode 100644 index 3431e8f00..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; -import { setPostgresCredentials } from '../../setPostgresCredentials'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; - - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if (context.serverType && context.serverType === PostgresServerType.Single) { - user = nonNullProp(context, 'longUserName'); - } else { - user = nonNullProp(context, 'shortUserName'); - } - const newServerName: string = nonNullProp(context, 'newServerName'); - - const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, 'adminPassword'); - const server: PostgresAbstractServer = nonNullProp(context, 'server'); - - await setPostgresCredentials(user, password, nonNullProp(server, 'id')); - const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } - - public shouldExecute(): boolean { - return true; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts deleted file mode 100644 index 654cd0430..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ /dev/null @@ -1,250 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { openUrl } from "../../../../utils/openUrl"; -import { AbstractSku, PostgresServerType } from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; - -interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; -} - -export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresServerWizardContext - ): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); - pricingTiers.push({ - label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), - onPicked: async () => { - await openUrl('https://aka.ms/AAcxhvm'); - }, data: undefined - }); - - context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } - - public async getPicks(serverType: PostgresServerType): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; - - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: option.group || localize('addlOptions', 'Additional Options') - }); - }); - return options; - } -} - -const recommendedGroup = localize('recommendGroup', 'Recommended'); -const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, -]; - -// Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 -// See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage -const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, -]; diff --git a/src/postgres/commands/deletePostgresDatabase.ts b/src/postgres/commands/deletePostgresDatabase.ts deleted file mode 100644 index a09520bde..000000000 --- a/src/postgres/commands/deletePostgresDatabase.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; - -export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); - const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresFunction.ts b/src/postgres/commands/deletePostgresFunction.ts deleted file mode 100644 index 9a4547428..000000000 --- a/src/postgres/commands/deletePostgresFunction.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; - -export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } - - const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresServer.ts b/src/postgres/commands/deletePostgresServer.ts deleted file mode 100644 index 733c6fca6..000000000 --- a/src/postgres/commands/deletePostgresServer.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; -import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; - -export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - await deleteDatabaseAccount(context, node, true) -} diff --git a/src/postgres/commands/deletePostgresStoredProcedure.ts b/src/postgres/commands/deletePostgresStoredProcedure.ts deleted file mode 100644 index 6abece79b..000000000 --- a/src/postgres/commands/deletePostgresStoredProcedure.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; - -export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } - - const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresTable.ts b/src/postgres/commands/deletePostgresTable.ts deleted file mode 100644 index bfdce33a2..000000000 --- a/src/postgres/commands/deletePostgresTable.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; - -export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); - await node.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/enterPostgresCredentials.ts b/src/postgres/commands/enterPostgresCredentials.ts deleted file mode 100644 index aa993c337..000000000 --- a/src/postgres/commands/enterPostgresCredentials.ts +++ /dev/null @@ -1,85 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { PostgresServerType } from '../abstract/models'; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -import { setPostgresCredentials } from "./setPostgresCredentials"; - -/** - * Get the username and password for the Postgres database from user input. - */ -async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string, password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), - stepName: 'enterPostgresUsername', - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } - }); - - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { - username += usernameSuffix; - } - - const password: string = await context.ui.showInputBox({ - prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), - stepName: 'enterPostgresPassword', - password: true, - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } - }); - - return { username, password }; -} - -/** - * Save the username and password in secure local storage. - */ -async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { - const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); - - const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); -} - -export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, 'azureName'); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, 'id'); - - const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); - - await persistUsernamePassword(id, serverName, username, password); - - treeItem.setCredentials(username, password); - await treeItem.refresh(context); -} diff --git a/src/postgres/commands/executePostgresQueryInDocument.ts b/src/postgres/commands/executePostgresQueryInDocument.ts deleted file mode 100644 index af5d3ca5e..000000000 --- a/src/postgres/commands/executePostgresQueryInDocument.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { EOL } from 'os'; -import * as path from 'path'; -import { ClientConfig, QueryResult } from 'pg'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import * as vscodeUtil from '../../utils/vscodeUtils'; -import { runPostgresQuery } from '../runPostgresQuery'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; -import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; - -export async function executePostgresQueryInDocument(context: IActionContext): Promise { - await loadPersistedPostgresDatabase(); - - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); - - const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - - if (!activeEditor?.document) { - throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); - } - - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); - ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); - - if (queryResult.rowCount) { - const fileExtension: string = path.extname(activeEditor.document.fileName); - const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); - const outputFileName: string = `${queryFileName}-output`; - - const fields: string[] = queryResult.fields.map(f => f.name); - let csvData: string = `${fields.join(',')}${EOL}`; - - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(',')}${EOL}`; - } - - await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); - } - await treeItem.refresh(context); -} diff --git a/src/postgres/commands/openPostgresFunction.ts b/src/postgres/commands/openPostgresFunction.ts deleted file mode 100644 index 26103970f..000000000 --- a/src/postgres/commands/openPostgresFunction.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { showPostgresQuery } from "../showPostgresQuery"; -import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; - -export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } - - await showPostgresQuery(treeItem); -} diff --git a/src/postgres/commands/openPostgresStoredProcedure.ts b/src/postgres/commands/openPostgresStoredProcedure.ts deleted file mode 100644 index 3c98ff743..000000000 --- a/src/postgres/commands/openPostgresStoredProcedure.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { showPostgresQuery } from "../showPostgresQuery"; -import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; - -export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } - - await showPostgresQuery(treeItem); -} diff --git a/src/postgres/commands/registerPostgresCommands.ts b/src/postgres/commands/registerPostgresCommands.ts deleted file mode 100644 index b861e00f7..000000000 --- a/src/postgres/commands/registerPostgresCommands.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { defaults } from "pg"; -import { languages } from "vscode"; -import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { openUrl } from "../../utils/openUrl"; -import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { configurePostgresFirewall } from "./configurePostgresFirewall"; -import { connectPostgresDatabase } from "./connectPostgresDatabase"; -import { copyConnectionString } from "./copyConnectionString"; -import { createPostgresDatabase } from "./createPostgresDatabase"; -import { createPostgresFunctionQuery } from "./createPostgresQuery/function/createPostgresFunctionQuery"; -import { createPostgresStoredProcedureQuery } from "./createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery"; -import { deletePostgresDatabase } from "./deletePostgresDatabase"; -import { deletePostgresFunction } from "./deletePostgresFunction"; -import { deletePostgresServer } from "./deletePostgresServer"; -import { deletePostgresStoredProcedure } from "./deletePostgresStoredProcedure"; -import { deletePostgresTable } from "./deletePostgresTable"; -import { enterPostgresCredentials } from "./enterPostgresCredentials"; -import { executePostgresQueryInDocument } from "./executePostgresQueryInDocument"; -import { openPostgresFunction } from "./openPostgresFunction"; -import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; - -export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); - - void loadPersistedPostgresDatabase(); - - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; - - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); - registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); - registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); - registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); - registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); - registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); -} - -export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); - if (persistedTreeItem) { - await connectPostgresDatabase(context, persistedTreeItem); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); -} - -export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); -} diff --git a/src/postgres/commands/setPostgresCredentials.ts b/src/postgres/commands/setPostgresCredentials.ts deleted file mode 100644 index 8df8260f6..000000000 --- a/src/postgres/commands/setPostgresCredentials.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from "../../extensionVariables"; -import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; - -interface IPersistedServer { - id: string; - username: string; -} - -export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); - - const newServer: IPersistedServer = { - id: serverId, - username - }; - - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); -} diff --git a/src/postgres/getClientConfig.ts b/src/postgres/getClientConfig.ts deleted file mode 100644 index bdc545945..000000000 --- a/src/postgres/getClientConfig.ts +++ /dev/null @@ -1,172 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Client, ClientConfig } from "pg"; -import { ConnectionOptions } from "tls"; -import { postgresDefaultPort } from "../constants"; -import { nonNullProp } from "../utils/nonNull"; -import { PostgresServerType } from "./abstract/models"; -import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; - -export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; -}; -export type PostgresClientConfigType = keyof PostgresClientConfigs; - -/** - * Test if the database can be connected to using the given client config. - * @throws if the client failed to connect to the database. - */ -export async function testClientConfig(clientConfig: ClientConfig): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } -} - -async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString(connectionString, databaseName); - } - return { connectionString: connectionString }; -} - -async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; - - if (!!username && !!password && !!host && !!port) { - return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; - } else { - return undefined; - } -} - -async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise -): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; -} - -export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise -): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] - }; - const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { - const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); - clientConfigs.connectionString = connectionStringClientConfig; - } - - return clientConfigs; -} - -// Postgres Single Server Root Cert, https://aka.ms/AA7wnvl -export const BaltimoreCyberTrustRoot: string = `-----BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE-----`; - -// Postgres Single Server Root Cert will be updated to DigiCertGlobalRootG2, https://aka.ms/AA7wnvl -export const DigiCertGlobalRootG2: string = `-----BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE-----`; - -// Postgres Flexible Server Root Cert, https://aka.ms/AAd75x5 -export const DigiCertGlobalRootCA: string = `-----BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE-----`; - diff --git a/src/postgres/getPostgresProcedureQueryRows.ts b/src/postgres/getPostgresProcedureQueryRows.ts deleted file mode 100644 index ad791ff2e..000000000 --- a/src/postgres/getPostgresProcedureQueryRows.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { QueryResult } from "pg"; -import { runPostgresQuery } from "./runPostgresQuery"; -import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; -import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; - -export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; -} - -function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, - p.proname as name, - p.oid as oid, - pg_get_function_arguments(p.oid) as args, - case when l.lanname = 'internal' then p.prosrc - else pg_get_functiondef(p.oid) - end as definition - from pg_proc p - left join pg_namespace n on p.pronamespace = n.oid - left join pg_language l on p.prolang = l.oid - where n.nspname not in ('pg_catalog', 'information_schema') - ${conditions} - order by name;`; -} - -export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { - let conditions: string; - - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } - - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } - - return rows; -} diff --git a/src/postgres/getTables.ts b/src/postgres/getTables.ts deleted file mode 100644 index ebc7d1c75..000000000 --- a/src/postgres/getTables.ts +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ClientConfig, QueryResult } from "pg"; -import { runPostgresQuery } from "./runPostgresQuery"; - -export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; -} - -const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, - concat('"', schemaname, '"."', tablename, '"')::regclass::oid as oid - from pg_catalog.pg_tables - left join ( - select column_name::text as columnname, table_name, table_schema - from information_schema.columns - ) columns on table_name = tablename and table_schema = schemaname - where schemaname != 'pg_catalog' AND schemaname != 'information_schema' - group by schemaname, tablename;`; - -export async function getTables(clientConfig: ClientConfig): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); - } - return tablesArray; -} diff --git a/src/postgres/postgresConnectionStrings.ts b/src/postgres/postgresConnectionStrings.ts deleted file mode 100644 index ea9ce9e2e..000000000 --- a/src/postgres/postgresConnectionStrings.ts +++ /dev/null @@ -1,74 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConnectionOptions, parse } from "pg-connection-string"; -import { postgresDefaultPort } from "../constants"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullProp } from "../utils/nonNull"; - -export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); -} - -export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); -} - -export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; -} - -export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; -} - -export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; - - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, 'host'); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } -} diff --git a/src/postgres/postgresConstants.ts b/src/postgres/postgresConstants.ts deleted file mode 100644 index 9bcf15144..000000000 --- a/src/postgres/postgresConstants.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export const invalidCredentialsErrorType: string = '28P01'; -export const firewallNotConfiguredErrorType: string = '28000'; -export const timeoutErrorType = 'ETIMEDOUT'; diff --git a/src/postgres/runPostgresQuery.ts b/src/postgres/runPostgresQuery.ts deleted file mode 100644 index b7d325364..000000000 --- a/src/postgres/runPostgresQuery.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Client, ClientConfig, QueryResult } from "pg"; - -export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } -} -export function wrapArgInQuotes(input: string): string { - return `"${input}"`; -} diff --git a/src/postgres/services/PostgresCodeLensProvider.ts b/src/postgres/services/PostgresCodeLensProvider.ts deleted file mode 100644 index 5d075eb3c..000000000 --- a/src/postgres/services/PostgresCodeLensProvider.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; -import { localize } from "../../utils/localize"; - -export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; - - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } - - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } - - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; - - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; - - let title: string; - if (!isInitialized) { - title = localize('initializing', 'Initializing...'); - } else if (isConnected) { - title = localize('connectedToDatabase', 'Connected to "{0}"', database); - } else { - title = localize('connectToDatabase', 'Connect to a database'); - } - - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && 'postgreSQL.connectDatabase' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - - if (isConnected) { - lenses.push({ - command: { - title: 'Execute Query', - command: 'postgreSQL.executeQuery' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - } - - return lenses; - }); - } -} diff --git a/src/postgres/showPostgresQuery.ts b/src/postgres/showPostgresQuery.ts deleted file mode 100644 index 7d6e2aa1d..000000000 --- a/src/postgres/showPostgresQuery.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { postgresBaseFileName, postgresFileExtension } from '../constants'; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; -import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; - -export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); -} diff --git a/src/postgres/tree/ClientConfigFactory.ts b/src/postgres/tree/ClientConfigFactory.ts deleted file mode 100644 index 271f5b92f..000000000 --- a/src/postgres/tree/ClientConfigFactory.ts +++ /dev/null @@ -1,86 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; -import { localize } from "../../utils/localize"; -import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; -import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; - -export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; - -/** - * Creates an object that can be used to execute a postgres query with connection test and telemetry. - */ -export class PostgresClientConfigFactory { - public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ - type: "azureAd" | "password" | "connectionString", - clientConfig: ClientConfig - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); - - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); - - const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; - - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } - - try { - await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = clientConfigType; - await testClientConfig(clientConfig); - }); - return { - type: clientConfigType, - clientConfig - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), - code: firewallNotConfiguredErrorType - }; - } else { - throw error; - } - } - } - - throw { - message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), - code: invalidCredentialsErrorType - }; - } -} diff --git a/src/postgres/tree/PostgresColumnTreeItem.ts b/src/postgres/tree/PostgresColumnTreeItem.ts deleted file mode 100644 index d284c8122..000000000 --- a/src/postgres/tree/PostgresColumnTreeItem.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; - -export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; - - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } - - public get id(): string { - return this.columnName; - } - - public get label(): string { - return this.columnName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('split-horizontal'); - } - -} diff --git a/src/postgres/tree/PostgresDatabaseTreeItem.ts b/src/postgres/tree/PostgresDatabaseTreeItem.ts deleted file mode 100644 index 05f7a4412..000000000 --- a/src/postgres/tree/PostgresDatabaseTreeItem.ts +++ /dev/null @@ -1,115 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// eslint-disable-next-line import/no-internal-modules -import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { ThemeIcon } from 'vscode'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresServerTreeItem } from './PostgresServerTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; - - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresFirewall', - label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.configureFirewall' - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } - - try { - const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig) - ]; - - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); - } - - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); - - if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresCredentials', - label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.enterCredentials' - }); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - return []; - } else { - throw error; - } - } - } - - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); - } - - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); - await this.refresh(context); - } -} diff --git a/src/postgres/tree/PostgresFunctionTreeItem.ts b/src/postgres/tree/PostgresFunctionTreeItem.ts deleted file mode 100644 index 0a26bf3f9..000000000 --- a/src/postgres/tree/PostgresFunctionTreeItem.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { IPostgresProceduresQueryRow } from "../getPostgresProcedureQueryRows"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; - -export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresFunction'; - public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; - - constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openFunction'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } - - public get label(): string { - return this.name; - } - - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); - } -} diff --git a/src/postgres/tree/PostgresFunctionsTreeItem.ts b/src/postgres/tree/PostgresFunctionsTreeItem.ts deleted file mode 100644 index 7d3904e83..000000000 --- a/src/postgres/tree/PostgresFunctionsTreeItem.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; - -export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresFunctions'; - public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; - public readonly label: string = 'Functions'; - public readonly childTypeLabel: string = 'Function'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } -} diff --git a/src/postgres/tree/PostgresResourcesTreeItemBase.ts b/src/postgres/tree/PostgresResourcesTreeItemBase.ts deleted file mode 100644 index b93cc9450..000000000 --- a/src/postgres/tree/PostgresResourcesTreeItemBase.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; - -// Base class for Postgres tree items whose children are individual resources -export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } - - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } -} diff --git a/src/postgres/tree/PostgresServerTreeItem.ts b/src/postgres/tree/PostgresServerTreeItem.ts deleted file mode 100644 index 20e7dbe76..000000000 --- a/src/postgres/tree/PostgresServerTreeItem.ts +++ /dev/null @@ -1,252 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as SingleModels from '@azure/arm-postgresql'; -import * as FlexibleModels from '@azure/arm-postgresql-flexible'; -import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import { ClientConfig } from 'pg'; -import { SemVer, coerce, gte } from 'semver'; -import * as vscode from 'vscode'; -import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { isIpInRanges } from '../../utils/getIp'; -import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; -import { getPublicIp } from '../commands/configurePostgresFirewall'; -import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -interface IPersistedServer { - id: string; - username: string; -} - -export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; - } - this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('PostgresServer.svg'); - } - - public get label(): string { - return this.azureName ? this.azureName : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); - dbNames = listOfDatabases.map(db => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map(db => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - 'invalidPostgresServer', - dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, - dbName => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); - } - const getChildrenTask: Promise = this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createPostgresDatabase', - validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) - }); - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, '11.0.0'); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); - - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); - } - - public async getFullConnectionString(): Promise { - - if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { - const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp(this, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); - const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } -} - -async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { - if (!name) { - return localize('NameCannotBeEmpty', 'Name cannot be empty.'); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize('NameExists', 'Database "{0}" already exists.', name); - } - return undefined; -} diff --git a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts b/src/postgres/tree/PostgresStoredProcedureTreeItem.ts deleted file mode 100644 index 503d0ae74..000000000 --- a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { IPostgresProceduresQueryRow } from "../getPostgresProcedureQueryRows"; -import { runPostgresQuery } from "../runPostgresQuery"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; - -export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresStoredProcedure'; - public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; - - constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openStoredProcedure'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } - - public get label(): string { - return this.name; - } - - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); - } -} diff --git a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts b/src/postgres/tree/PostgresStoredProceduresTreeItem.ts deleted file mode 100644 index 1c516e00f..000000000 --- a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; - -export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresStoredProcedures'; - public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = 'Stored Procedures'; - public readonly childTypeLabel: string = 'Stored Procedure'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } -} diff --git a/src/postgres/tree/PostgresTableTreeItem.ts b/src/postgres/tree/PostgresTableTreeItem.ts deleted file mode 100644 index ef5d87c2c..000000000 --- a/src/postgres/tree/PostgresTableTreeItem.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IPostgresTable } from '../getTables'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; - - private _isDuplicate: boolean; - - constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } - - public get id(): string { - return String(this.table.oid); - } - - public get label(): string { - return this.table.name; - } - - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); - } - -} diff --git a/src/postgres/tree/PostgresTablesTreeItem.ts b/src/postgres/tree/PostgresTablesTreeItem.ts deleted file mode 100644 index c18c065db..000000000 --- a/src/postgres/tree/PostgresTablesTreeItem.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from 'vscode'; -import { getTables, IPostgresTable } from "../getTables"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; - -export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = 'Tables'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); - } - return tables.map(table => new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } -} diff --git a/src/resolver/AppResolver.ts b/src/resolver/AppResolver.ts deleted file mode 100644 index 0f75cdf29..000000000 --- a/src/resolver/AppResolver.ts +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; -import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; -import { tryGetExperience } from "../AzureDBExperiences"; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from "../extensionVariables"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { PostgresAbstractServer } from "../postgres/abstract/models"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; -import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; -import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; - -const resourceTypes = [ - 'microsoft.documentdb/databaseaccounts', - 'microsoft.dbforpostgresql/servers', - 'microsoft.dbforpostgresql/flexibleservers' -]; - -export class DatabaseResolver implements AppResourceResolver { - public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { - return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); - try { - const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); - const name = nonNullProp(resource, 'name'); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; - - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ ...context, ...subContext }); - const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); - const experience = tryGetExperience(databaseAccount); - - return experience?.api === 'MongoDB' ? - new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : - new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? - await createPostgreSQLClient({ ...context, ...subContext }) : - await createPostgreSQLFlexibleClient({ ...context, ...subContext }); - - postgresServer = await postgresClient.servers.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); - - return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - }); - } - - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } -} diff --git a/src/resolver/DatabaseWorkspaceProvider.ts b/src/resolver/DatabaseWorkspaceProvider.ts deleted file mode 100644 index 14e50d643..000000000 --- a/src/resolver/DatabaseWorkspaceProvider.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; -import { Disposable } from "vscode"; -import { ext } from "../extensionVariables"; -import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; - - -export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise { - - return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - }); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } -} - diff --git a/src/resolver/ResolvedDatabaseAccountResource.ts b/src/resolver/ResolvedDatabaseAccountResource.ts deleted file mode 100644 index 0222dded7..000000000 --- a/src/resolver/ResolvedDatabaseAccountResource.ts +++ /dev/null @@ -1,57 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; - -export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue) - this.maskedValuestoAdd.push(...ti.valuesToMask); - } -} diff --git a/src/resolver/ResolvedDocDBAccountResource.ts b/src/resolver/ResolvedDocDBAccountResource.ts deleted file mode 100644 index cf1bfc4bc..000000000 --- a/src/resolver/ResolvedDocDBAccountResource.ts +++ /dev/null @@ -1,32 +0,0 @@ - - -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } -} diff --git a/src/resolver/ResolvedMongoAccountResource.ts b/src/resolver/ResolvedMongoAccountResource.ts deleted file mode 100644 index 4f45486ef..000000000 --- a/src/resolver/ResolvedMongoAccountResource.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - root: IMongoTreeRoot; - - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - } -} diff --git a/src/resolver/ResolvedPostgresServerResource.ts b/src/resolver/ResolvedPostgresServerResource.ts deleted file mode 100644 index a1e35acf3..000000000 --- a/src/resolver/ResolvedPostgresServerResource.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { ClientConfig } from "pg"; -import { PostgresServerType } from "../postgres/abstract/models"; -import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise - deletePostgresCredentials: () => Promise - getFullConnectionString: () => Promise - validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise - isFirewallRuleSet: (context: IActionContext) => Promise - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } -} diff --git a/src/table/tree/TableAccountTreeItem.ts b/src/table/tree/TableAccountTreeItem.ts deleted file mode 100644 index 0d3b86e38..000000000 --- a/src/table/tree/TableAccountTreeItem.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; - -export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public initChild(): AzExtTreeItem { - throw new Error('Table Accounts are not supported yet.'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'tableNotSupported', - label: 'Table Accounts are not supported yet.' - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } - - public isAncestorOfImpl(): boolean { - return false; - } -} diff --git a/src/tree/AttachedAccountsTreeItem.ts b/src/tree/AttachedAccountsTreeItem.ts deleted file mode 100644 index d854e506f..000000000 --- a/src/tree/AttachedAccountsTreeItem.ts +++ /dev/null @@ -1,420 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { removeTreeItemFromCache } from '../commands/api/apiCache'; -import { emulatorPassword, isWindows } from '../constants'; -import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; -import { connectToMongoClient } from '../mongo/connectToMongoClient'; -import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; -import { getSecretStorageKey } from '../utils/getSecretStorageKey'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; - -interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; -} - -export const AttachedAccountSuffix: string = 'Attached'; -export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; - -const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; - -export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); - public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; - public readonly label: string = 'Attached Database Accounts'; - public childTypeLabel: string = 'Account'; - public suppressMaskLabel = true; - - private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = 'cosmosDBAttachedAccounts'; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('plug'); - } - - public static validateMongoConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); - } - - private static validateDocDBConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachDatabaseAccount', - label: 'Attach Database Account...', - commandId: 'cosmosDB.attachDatabaseAccount', - includeInTreeItemPicker: true - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachEmulator', - label: 'Attach Emulator...', - commandId: 'cosmosDB.attachEmulator', - includeInTreeItemPicker: true - }); - return isWindows ? [attachDatabaseAccount, attachEmulator] : - [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = 'mongodb://host:port'; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; - } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { - placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); - validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = 'AccountEndpoint=...;AccountKey=...'; - validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = (await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: 'Enter the connection string for your database account', - stepName: 'attachNewAccountConnectionString', - validateInput: validateInput, - value: defaultValue - })).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { - const treeItem = await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core) - ], - { - placeHolder: "Select a Database Account API...", - stepName: 'attachEmulator' - }); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); - if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.find(s => s.id === treeItem.id)) { - void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get(this._serviceName); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all(accounts.map(async account => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof (account) === 'string') { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${getExperienceFromApi(api).shortName})`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); - persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); - })); - } - - return persistedAccounts; - } - - private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error(`Unexpected account node "${node.constructor.name}".`); - } - return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; - }); - await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); - } -} - -class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); - - public get credentials(): never { - throw this._error; - } - - public get subscriptionDisplayName(): never { - throw this._error; - } - - public get subscriptionId(): never { - throw this._error; - } - - public get subscriptionPath(): never { - throw this._error; - } - - public get tenantId(): never { - throw this._error; - } - - public get userId(): never { - throw this._error; - } - - public get environment(): never { - throw this._error; - } - - public get isCustomCloud(): never { - throw this._error; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} diff --git a/src/tree/AzureAccountTreeItemWithAttached.ts b/src/tree/AzureAccountTreeItemWithAttached.ts deleted file mode 100644 index 172cd598f..000000000 --- a/src/tree/AzureAccountTreeItemWithAttached.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; -import { ext } from '../extensionVariables'; -import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; - -export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } - - public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } - - public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); - return children.concat(ext.attachedAccountsNode); - } - - public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } -} diff --git a/src/tree/AzureDBAPIStep.ts b/src/tree/AzureDBAPIStep.ts deleted file mode 100644 index 8a11fdc95..000000000 --- a/src/tree/AzureDBAPIStep.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; -import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; -import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; -import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; -import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; -import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; -import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; -import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; -import { localize } from '../utils/localize'; -import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; -import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; -import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; -import { IAzureDBWizardContext } from './IAzureDBWizardContext'; - -export class AzureDBAPIStep extends AzureWizardPromptStep { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); - - const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { - placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') - }); - - context.defaultExperience = result.data; - } - - public async getSubWizard(context: IAzureDBWizardContext): Promise> { - let promptSteps: AzureWizardPromptStep[]; - let executeSteps: AzureWizardExecuteStep[]; - if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(['Microsoft.DocumentDB']) - ]; - } - return { promptSteps, executeSteps }; - } - - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts deleted file mode 100644 index b46453e3a..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { - - public async prompt(context: ICosmosDBWizardContext): Promise { - - const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') - const picks: IAzureQuickPickItem[] = [ - { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, - { label: localize('serverlessOption', 'Serverless'), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; - - do { - pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); - if (pick === learnMore) { - await openUrl('https://aka.ms/cosmos-models'); - } - } while (pick === learnMore); - - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; - } - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts deleted file mode 100644 index 4bd469b84..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ /dev/null @@ -1,63 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; -import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { Progress } from 'vscode'; -import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const locationName: string = (await LocationListStep.getLocation(context)).name; - const defaultExperience = nonNullProp(context, 'defaultExperience'); - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const accountName = nonNullProp(context, 'newServerName'); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: 'Standard', - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, - }; - - if (defaultExperience?.api === 'MongoDB') { - options.apiProperties = { serverVersion: '3.6' }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts deleted file mode 100644 index 87ef6be61..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountNameStep extends AzureNameStep { - - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => validateCosmosDBAccountName(name, client) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} - -async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { - name = name ? name.trim() : ''; - - const min = 3; - const max = 31; - - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } -} diff --git a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts deleted file mode 100644 index 61666a859..000000000 --- a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; - -export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; - -} diff --git a/src/tree/IAzureDBWizardContext.ts b/src/tree/IAzureDBWizardContext.ts deleted file mode 100644 index fd84ff0d5..000000000 --- a/src/tree/IAzureDBWizardContext.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { Experience } from '../AzureDBExperiences'; - -export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - - newServerName?: string; - defaultExperience?: Experience; - -} diff --git a/src/tree/SubscriptionTreeItem.ts b/src/tree/SubscriptionTreeItem.ts deleted file mode 100644 index 910d8d970..000000000 --- a/src/tree/SubscriptionTreeItem.ts +++ /dev/null @@ -1,158 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; -import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from '../extensionVariables'; -import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; -import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from '../utils/activityUtils'; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { localize } from '../utils/localize'; -import { nonNullProp } from '../utils/nonNull'; -import { AzureDBAPIStep } from './AzureDBAPIStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; - -export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = 'Account'; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - - //Postgres - const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); - const postgresServers: PostgresAbstractServer[] = [ - ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), - ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), - ]; - - const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - postgresServers, - 'invalidPostgreSQLAccount', - async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); - const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - accounts, - 'invalidCosmosDBAccount', - async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep() - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize('createDBServerMsg', 'Create new Azure Database Server') - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp(wizardContext, 'newServerName'); - wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { - const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, 'server'); - const host = nonNullProp(server, 'fullyQualifiedDomainName'); - const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); - const password: string = nonNullProp(wizardContext, 'adminPassword'); - const connectionString: string = createPostgresConnectionString(host, undefined, username, password); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return typeof contextValue !== 'string' || !/attached/i.test(contextValue); - } - - public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, 'id'); - const name: string = nonNullProp(databaseAccount, 'name'); - const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); - const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = 'retrywrites'; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, 'false'); - } - - // Use the default connection string - return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); - } else { - const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - case "Graph": { - const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); - return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - - } - } - } - public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { - const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } -} diff --git a/src/utils/InteractiveChildProcess.ts b/src/utils/InteractiveChildProcess.ts deleted file mode 100644 index 26129b342..000000000 --- a/src/utils/InteractiveChildProcess.ts +++ /dev/null @@ -1,176 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as cp from 'child_process'; -import * as os from 'os'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { Event, EventEmitter } from 'vscode'; -import { improveError } from './improveError'; - -// We add these when we display to the output window -const stdInPrefix = '> '; -const stdErrPrefix = 'ERR> '; -const errorPrefix = 'Error running process: '; - -const processStartupTimeout = 60; - -export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; -} - -export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create(options: IInteractiveChildProcessOptions): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess(options); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(' '); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false - }; - - this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); - this._childProc = cp.spawn(this._options.command, this._options.args, options); - - this._childProc.stdout?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on('error', (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on('close', (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel(text: string, displayPrefix?: string): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = (filteredText !== text && filteredText === ''); - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); - } - - return text; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} diff --git a/src/utils/activityUtils.ts b/src/utils/activityUtils.ts deleted file mode 100644 index fefd2fe00..000000000 --- a/src/utils/activityUtils.ts +++ /dev/null @@ -1,15 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { ext } from "../extensionVariables"; -import { getWorkspaceSetting } from "./settingUtils"; - -export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), - }; -} diff --git a/src/utils/array.ts b/src/utils/array.ts deleted file mode 100644 index 06f095e8d..000000000 --- a/src/utils/array.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { - return arr ? arr.filter(element => element instanceof genericConstructor) : []; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { - return arr && arr.find(element => element instanceof genericConstructor); -} diff --git a/src/utils/azureClients.ts b/src/utils/azureClients.ts deleted file mode 100644 index 9be19e959..000000000 --- a/src/utils/azureClients.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; -import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; - -// Lazy-load @azure packages to improve startup performance. -// NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript - -export async function createCosmosDBClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); -} - -export async function createPostgreSQLClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); -} - -export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); -} diff --git a/src/utils/azureUtils.ts b/src/utils/azureUtils.ts deleted file mode 100644 index b0017314b..000000000 --- a/src/utils/azureUtils.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); - - if (!matches || matches.length < 5) { - throw new Error('Invalid Azure Resource Id'); - } - - return matches[4]; -} diff --git a/src/utils/cp.ts b/src/utils/cp.ts deleted file mode 100644 index 660dc3068..000000000 --- a/src/utils/cp.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as cp from 'child_process'; - -export async function commandSucceeds(command: string, ...args: string[]): Promise { - return await new Promise(resolve => { - cp.spawn(command, args) - .on('error', _error => resolve(false)) - .on('exit', code => resolve(code === 0)); - }); -} diff --git a/src/utils/getIp.ts b/src/utils/getIp.ts deleted file mode 100644 index 20d22e989..000000000 --- a/src/utils/getIp.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { isIPv4 } from 'net'; -import { localize } from './localize'; - -export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); -} - -export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, 'https://api.ipify.org/'), - () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; -} - -const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); - -function ipToNum(ip: string) { - return Number( - ip.split(".") - .map(d => ("000" + d).substring(-3)) - .join("") - ); -} - -async function getPublicIpv4Https(context: IActionContext, url: string): Promise { - const req = await sendRequestWithTimeout(context, { - method: 'GET', - url, - }, 5000, undefined); - - const ip = req.bodyAsText; - - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } - - return ip; -} diff --git a/src/utils/getSecretStorageKey.ts b/src/utils/getSecretStorageKey.ts deleted file mode 100644 index 80e116737..000000000 --- a/src/utils/getSecretStorageKey.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; -} diff --git a/src/utils/improveError.ts b/src/utils/improveError.ts deleted file mode 100644 index 27ff1f014..000000000 --- a/src/utils/improveError.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from "@microsoft/vscode-azext-utils"; - -export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } - - return error; -} diff --git a/src/utils/localize.ts b/src/utils/localize.ts deleted file mode 100644 index 2aee3fa12..000000000 --- a/src/utils/localize.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vscode-nls'; - -export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/src/utils/nonNull.ts b/src/utils/nonNull.ts deleted file mode 100644 index d7104b4f8..000000000 --- a/src/utils/nonNull.ts +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { isNullOrUndefined } from 'util'; - -/** - * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed - * for the property and will give a compile error if the given name is not a property of the source. - */ -export function nonNullProp(source: TSource, name: TKey): NonNullable { - const value: NonNullable = >source[name]; - return nonNullValue(value, name); -} - -/** - * Validates that a given value is not null and not undefined. - */ -export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { - if (isNullOrUndefined(value)) { - throw new Error( - 'Internal error: Expected value to be neither null nor undefined' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } - - return value; -} - -/** - * Validates that a given string is not null, undefined, nor empty - */ -export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { - if (!value) { - throw new Error( - 'Internal error: Expected value to be neither null, undefined, nor empty' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } - - return value; -} diff --git a/src/utils/openUrl.ts b/src/utils/openUrl.ts deleted file mode 100644 index 0be3f5bbb..000000000 --- a/src/utils/openUrl.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as open from 'open'; - -export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); - - await open(url); -} diff --git a/src/utils/randomUtils.ts b/src/utils/randomUtils.ts deleted file mode 100644 index 7a313f23a..000000000 --- a/src/utils/randomUtils.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as crypto from "crypto"; - -export namespace randomUtils { - export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { - return crypto.createHash('sha256').update(s).digest(encoding); - } - - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString('hex').slice(0, length); - } -} diff --git a/src/utils/settingUtils.ts b/src/utils/settingUtils.ts deleted file mode 100644 index 0ac1004c2..000000000 --- a/src/utils/settingUtils.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; -import { ext } from "../extensionVariables"; - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - await projectConfiguration.update(section, value, ConfigurationTarget.Global); -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); - return result && result.globalValue; -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); - return projectConfiguration.get(key); -} - -/** - * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } -} diff --git a/src/utils/timeout.ts b/src/utils/timeout.ts deleted file mode 100644 index cc5ffb2d6..000000000 --- a/src/utils/timeout.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -const timedOutMessage = "Execution timed out"; - -/** - * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. - */ -export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } - - throw err; - } -} - -/** - * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. - */ -export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout( - () => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, - timeoutMs); - - let value: T; - let error; - - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); -} diff --git a/src/utils/vscodeUtils.ts b/src/utils/vscodeUtils.ts deleted file mode 100644 index d05f84872..000000000 --- a/src/utils/vscodeUtils.ts +++ /dev/null @@ -1,103 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ItemDefinition } from '@azure/cosmos'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; -import { getRootPath } from './workspacUtils'; - -export interface IDisposable { - dispose(): void; -} - -export function dispose(disposables: T[]): T[] { - disposables.forEach(d => d.dispose()); - return []; -} - -export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; -} - -export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); - const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); - await writeToEditor(editor, data); -} - -export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt(editor.document.lineCount - 1); - editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); - } - - editBuilder.insert(new vscode.Position(0, 0), data); - }); -} - -async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { - let count: number = 1; - const maxCount: number = 1024; - - while (count < maxCount) { - const fileSuffix = count === 0 ? '' : '-' + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; - - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } - - throw new Error('Could not find unique name for new file.'); -} - -export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join('/'); -} - -function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); -} - -export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== 'object') { - return String(value); - } - } - } - return String(document._id); -} - -function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; -} diff --git a/src/utils/workspacUtils.ts b/src/utils/workspacUtils.ts deleted file mode 100644 index 20b60da11..000000000 --- a/src/utils/workspacUtils.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { nonNullValue } from './nonNull'; - -export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; -} - -export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); -} diff --git a/src/utils/wrapError.ts b/src/utils/wrapError.ts deleted file mode 100644 index f6ec5d2b5..000000000 --- a/src/utils/wrapError.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; - -export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } - - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } - - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); -} diff --git a/src/vscode-cosmosdb.api.d.ts b/src/vscode-cosmosdb.api.d.ts deleted file mode 100644 index d5e4416c1..000000000 --- a/src/vscode-cosmosdb.api.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem(query: TreeItemQuery): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; -} - -export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; -} - -export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - } - - docDBData?: { - masterKey: string; - documentEndpoint: string; - } - - postgresData?: { - username: string | undefined; - password: string | undefined; - } - -} - -export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; -} - -export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; - -export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; - -export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; -} - -export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - } -} diff --git a/src/vscode-cosmosdbgraph.api.d.ts b/src/vscode-cosmosdbgraph.api.d.ts deleted file mode 100644 index 95cde2531..000000000 --- a/src/vscode-cosmosdbgraph.api.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface CosmosDBGraphExtensionApi { - apiVersion: string; - - openGraphExplorer(config: IGraphConfiguration): Promise; -} - -export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; -} - -export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; - - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; - - key: string; - databaseName: string; - graphName: string; - tabTitle: string; -} diff --git a/test/.eslintrc.js b/test/.eslintrc.js deleted file mode 100644 index afff31b69..000000000 --- a/test/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - "extends": [ - "@microsoft/eslint-config-azuretools", - "@microsoft/eslint-config-azuretools/test" - ] -}; diff --git a/test/attachedAccountsTreeItem.test.ts b/test/attachedAccountsTreeItem.test.ts deleted file mode 100644 index be76cad51..000000000 --- a/test/attachedAccountsTreeItem.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { AttachedAccountsTreeItem, MONGO_CONNECTION_EXPECTED } from '../extension.bundle'; - -function assertConnectionValid(connectionString: string, expected: string | undefined): void { - const actual = AttachedAccountsTreeItem.validateMongoConnectionString(connectionString); - assert.equal(actual, expected); -} - -suite(`attachedAccountsTreeItem`, () => { - suite(`validateDocDBConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - test('allows "mongodb://"', () => assertConnectionValid(`mongodb://your-mongo.documents.azure.com:10255`, undefined)); - - test('allows "mongodb+srv://"', () => assertConnectionValid(`mongodb+srv://usr:pwd@mongodb.net:27017`, undefined)); - - test('rejects bad prefix', () => assertConnectionValid(`http://localhost/`, MONGO_CONNECTION_EXPECTED)); - - test('rejects null', () => assertConnectionValid(null!, MONGO_CONNECTION_EXPECTED)); - }); -}); diff --git a/test/docDBConnectionStrings.test.ts b/test/docDBConnectionStrings.test.ts deleted file mode 100644 index e04c0a96f..000000000 --- a/test/docDBConnectionStrings.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { emulatorPassword, parseDocDBConnectionString } from '../extension.bundle'; - -function testConnectionString(connectionString: string, expectedEndpoint: string, expectedKey: string, expectedDatabaseName: string | undefined): void { - const parsedCS = parseDocDBConnectionString(connectionString); - assert.equal(parsedCS.documentEndpoint, expectedEndpoint); - assert.equal(parsedCS.masterKey, expectedKey); - assert.equal(parsedCS.databaseName, expectedDatabaseName); -} - -suite(`docDBConnectionStrings`, () => { - test(`Without database name`, () => { - // Testing different ordering, different use of ';', different casing, etc. - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString(' AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/; AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('accountendpoint=https://abcdef.documents.azure.com:443/;accountkey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - - // emulator - testConnectionString(`AccountEndpoint=https://localhost:10255/;AccountKey=${emulatorPassword};`, 'https://localhost:10255/', emulatorPassword, undefined); - - // Testing other properties - const parsedCS = parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;'); - assert.equal(parsedCS.hostName, 'abcdef.documents.azure.com'); - assert.equal(parsedCS.port, '443'); - assert.equal(parsedCS.accountId, 'abcdef.documents.azure.com:443'); - assert.equal(parsedCS.fullId, 'abcdef.documents.azure.com:443'); - }); - - test(`With database name`, () => { - // Testing different ordering, different use of ';', different casing, etc. - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=abcd;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('Database=abcd;AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - - // Testing other properties - const parsedCS = parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd'); - assert.equal(parsedCS.hostName, 'abcdef.documents.azure.com'); - assert.equal(parsedCS.port, '443'); - assert.equal(parsedCS.accountId, 'abcdef.documents.azure.com:443'); - assert.equal(parsedCS.fullId, 'abcdef.documents.azure.com:443/abcd'); - }); - - test(`Invalid connection strings`, () => { - assert.throws(() => parseDocDBConnectionString('')); - assert.throws(() => parseDocDBConnectionString('AccountKey=abcdef==')); - assert.throws(() => parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/')); - assert.throws(() => parseDocDBConnectionString('mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb')); - }); -}); diff --git a/test/documentLabel.test.ts b/test/documentLabel.test.ts deleted file mode 100644 index 29cde94c8..000000000 --- a/test/documentLabel.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { getDocumentTreeItemLabel } from '../extension.bundle'; - -suite("Document Label Tests", () => { - test("Non-zero number", () => { - const doc = { name: 4, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), 4); - }); - - test("zero (number)", () => { - const doc = { name: 0, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), 0); - }); - - test("Empty string", () => { - const doc = { name: "", _id: "" }; - assert.equal(getDocumentTreeItemLabel(doc), ""); - }); - - test("Null", () => { - const doc = { name: null, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), doc._id); - }); -}); diff --git a/test/global.test.ts b/test/global.test.ts deleted file mode 100644 index f3fd38670..000000000 --- a/test/global.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TestOutputChannel, TestUserInput } from '@microsoft/vscode-azext-dev'; -import * as vscode from 'vscode'; -import { ext, registerOnActionStartHandler } from '../extension.bundle'; - -// Runs before all tests -suiteSetup(async function (this: Mocha.Context): Promise { - this.timeout(2 * 60 * 1000); - await vscode.commands.executeCommand('azureDatabases.refresh'); // activate the extension before tests begin - ext.outputChannel = new TestOutputChannel(); - - registerOnActionStartHandler(context => { - // Use `TestUserInput` by default so we get an error if an unexpected call to `context.ui` occurs, rather than timing out - context.ui = new TestUserInput(vscode); - }); -}); diff --git a/test/improveError.test.ts b/test/improveError.test.ts deleted file mode 100644 index 25ae0a35e..000000000 --- a/test/improveError.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { improveError } from '../extension.bundle'; - -suite("improveError", () => { - test("no change", () => { - const msg: string = "where is c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe?"; - const improved: unknown = improveError(msg); - - assert.equal(parseError(improved).message, msg); - }); - - test("spawn ENOENT", () => { - const msg: string = "spawn c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe ENOENT"; - const improved: unknown = improveError(msg); - - assert.equal(parseError(improved).message, "Could not find c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe"); - }); -}); diff --git a/test/index.ts b/test/index.ts deleted file mode 100644 index bfb035776..000000000 --- a/test/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as glob from 'glob'; -import * as Mocha from 'mocha'; -import * as path from 'path'; - -export async function run(): Promise { - const options: Mocha.MochaOptions = { - ui: 'tdd', - color: true, - reporter: 'mocha-multi-reporters', - reporterOptions: { - reporterEnabled: 'spec, mocha-junit-reporter', - mochaJunitReporterReporterOptions: { - mochaFile: path.resolve(__dirname, '..', '..', 'test-results.xml') - } - } - }; - - addEnvVarsToMochaOptions(options); - console.log(`Mocha options: ${JSON.stringify(options, undefined, 2)}`); - - const mocha = new Mocha(options); - console.log("get files"); - const files: string[] = await new Promise((resolve, reject) => { - // tests in unit/ folder must run without vscode context. - // Skip them when running integration tests in a vscode instance. - glob('{!(unit)/,}*.test.js', { cwd: __dirname }, (err, result) => { - err ? reject(err) : resolve(result); - }); - }); - files.forEach(f => mocha.addFile(path.resolve(__dirname, f))); - - const failures = await new Promise(resolve => mocha.run(resolve)); - if (failures > 0) { - throw new Error(`${failures} tests failed.`); - } -} - -function addEnvVarsToMochaOptions(options: Mocha.MochaOptions): void { - for (const envVar of Object.keys(process.env)) { - const match: RegExpMatchArray | null = envVar.match(/^mocha_(.+)/i); - if (match) { - const [, option] = match; - let value: string | number = process.env[envVar] || ''; - if (typeof value === 'string' && !isNaN(parseInt(value))) { - value = parseInt(value); - } - (options)[option] = value; - } - } -} diff --git a/test/mongoConnectionStrings.test.ts b/test/mongoConnectionStrings.test.ts deleted file mode 100644 index 4560342a7..000000000 --- a/test/mongoConnectionStrings.test.ts +++ /dev/null @@ -1,165 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { addDatabaseToAccountConnectionString, emulatorPassword, encodeMongoConnectionString, getDatabaseNameFromConnectionString, isCosmosEmulatorConnectionString } from '../extension.bundle'; - -function testDatabaseToAccountConnectionString(connectionString: string, databaseName: string, expectedConnectionString: string | undefined): void { - const databaseConnectionString = addDatabaseToAccountConnectionString(connectionString, databaseName); - assert.equal(databaseConnectionString, expectedConnectionString); -} - -function testDatabaseNameFromConectionString(connectionString: string, expectedDatabaseName: string | undefined): void { - const databaseName = getDatabaseNameFromConnectionString(connectionString); - assert.equal(databaseName, expectedDatabaseName); -} - -function testIsCosmosEmulatorConnectionString(connectionString: string, expected: boolean): void { - const actual: boolean = isCosmosEmulatorConnectionString(connectionString); - assert.equal(actual, expected); -} - -function testEncodeMongoConnectionString(connectionString: string, expectedConnectionString: string): void { - connectionString = encodeMongoConnectionString(connectionString); - assert.equal(connectionString, expectedConnectionString); -} - -suite(`mongoCollectionStrings`, () => { - test(`getDatabaseNameFromConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - testDatabaseNameFromConectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, undefined); - testDatabaseNameFromConectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, 'our-mongo'); - - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, undefined); - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, undefined); - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/dbname`, `dbname`); - - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, undefined); - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test`, 'my-database'); - - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, undefined); - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, undefined); - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/db`, 'db'); - - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/`, undefined); - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/db`, 'db'); - - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, undefined); - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB`, 'MYDB'); - - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, undefined); - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, 'my_db'); - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, undefined); - testDatabaseNameFromConectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, 'hello'); - testDatabaseNameFromConectionString(`mongodb://localhost`, undefined); - testDatabaseNameFromConectionString(`mongodb://localhost/db`, 'db'); - testDatabaseNameFromConectionString(`mongodb://sysop:moon@localhost/records`, 'records'); - testDatabaseNameFromConectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/db`, 'db'); - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc`, 'abc'); - - // special characters - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl`, 'def-ghi_jkl'); - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/Icantlikespaces`, 'Icantlikespaces'); - - // emulator: mongodb://localhost:C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==@localhost:10255?ssl=true - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin?ssl=true`, 'admin'); - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin-master?ssl=true`, 'admin-master'); - // test characters mentioned in : https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Database-Names-for-Windows - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin!@%^()-_,[]?ssl=true`, 'admin!@%^()-_,[]'); - - }); - - test('addDatabaseToAccountConnectionString', () => { - testDatabaseToAccountConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, 'somedatabase', 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/somedatabase?ssl=true&replicaSet=globaldb'); - testDatabaseToAccountConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, 'our-mongo', 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb'); - - testDatabaseToAccountConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, 'mydata', 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/mydata'); - testDatabaseToAccountConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, 'database', 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/database'); - testDatabaseToAccountConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, 'database', 'mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database'); - - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, 'my-database', 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test'); - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, 'my-database', 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?'); - - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, 'undefined', 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined'); - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, 'undefined', 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined'); - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, '(NoSQL)data', 'mongodb://r1.example.net:27017,r2.example.net:27017/(NoSQL)data'); - - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, 'undefined', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/undefined?replicaSet=mySet&authSource=authDB'); - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, 'MYDB', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB'); - - testDatabaseToAccountConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, 'basetoadd', 'mongodb+srv://server.example.com/basetoadd?connectTimeoutMS=300000&authSource=aDifferentAuthDB?'); - - testDatabaseToAccountConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, '', 'mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB'); - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, 'not_mydatabase', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/not_mydatabase?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB'); - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, '', 'mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000'); - testDatabaseToAccountConnectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, 'hellno', 'mongodb://host.example.com/hellno?readPreference=secondary&maxStalenessSeconds=120'); - testDatabaseToAccountConnectionString(`mongodb://localhost`, '', 'mongodb://localhost/'); - testDatabaseToAccountConnectionString(`mongodb://localhost/db`, 'new{}db', `mongodb://localhost/${encodeURIComponent("new{}db")}`); - testDatabaseToAccountConnectionString(`mongodb://sysop:moon@localhost/records`, 'records', 'mongodb://sysop:moon@localhost/records'); - testDatabaseToAccountConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, 'notfun', 'mongodb://%2Ftmp%2Fmongodb-27017.sock/notfun'); - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, 'notsure', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/notsure?ssl=true'); - - // special characters - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, 'def-ghi_jkl', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl?'); - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, 'icantlikespaces', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/icantlikespaces'); - - // Emulator - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin?ssl=true`); - // Collection within emulator - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin-master', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin-master?ssl=true`); - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin!@%^()-_,[]', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/${encodeURIComponent("admin!@%^()-_,[]")}?ssl=true`); - }); - - test('isCosmosEmulatorConnectionString', () => { - testIsCosmosEmulatorConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, false); - testIsCosmosEmulatorConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, false); - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, false); - testIsCosmosEmulatorConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, false); - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, false); - - testIsCosmosEmulatorConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, false); - testIsCosmosEmulatorConnectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost/db`, false); - testIsCosmosEmulatorConnectionString(`mongodb://sysop:moon@localhost/records`, false); - testIsCosmosEmulatorConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc...`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, false); - - // Emulator - testIsCosmosEmulatorConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, true); - testIsCosmosEmulatorConnectionString(`mongodb://127.0.0.1:${encodeURIComponent(emulatorPassword)}@127.0.0.1:10255/?ssl=true`, true); - testIsCosmosEmulatorConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/database?ssl=true`, true); - }); - - test('encodeMongoConnectionString', () => { - testEncodeMongoConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg%3D%3D@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`); - testEncodeMongoConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`); - testEncodeMongoConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`); - testEncodeMongoConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`); - testEncodeMongoConnectionString(`mongodb://localhost`, `mongodb://localhost`); - testEncodeMongoConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, `mongodb://localhost:${encodeURIComponent(encodeURIComponent(emulatorPassword))}@localhost:10255/?ssl=true`); - testEncodeMongoConnectionString(`mongodb://username@example.com:password@localhost/`, `mongodb://username%40example.com:password@localhost/`); - testEncodeMongoConnectionString(`mongodb://crazy@:/%username:even@crazier%/password@localhost/`, `mongodb://crazy%40%3A%2F%25username:even%40crazier%25%2Fpassword@localhost/`); - }); -}); diff --git a/test/mongoGetCommand.test.ts b/test/mongoGetCommand.test.ts deleted file mode 100644 index 5a72eae5e..000000000 --- a/test/mongoGetCommand.test.ts +++ /dev/null @@ -1,1138 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { Position } from 'vscode'; -import { findCommandAtPosition, getAllCommandsFromText, MongoCommand, nonNullProp, ObjectID, ObjectId } from '../extension.bundle'; - -function expectSingleCommand(text: string): MongoCommand { - const commands = getAllCommandsFromText(text); - if (commands.length > 1) { - assert.ok(false, "Too many commands found"); - } - - return commands[0]; -} - -function testParse( - text: string, - expectedCommand: { collection: string | undefined, name: string | undefined, args: any[] | undefined, firstErrorText?: string } | undefined -): void { - function testCore(coreText: string): void { - const command = expectSingleCommand(coreText); - if (expectedCommand) { - assert.ok(command, "Expected a command, but found none"); - - assert.equal(command.collection || "", expectedCommand.collection || "", "Parsed collection name is not correct"); - assert.equal(command.name || "", expectedCommand.name || "", "Parsed command name is not correct"); - - const actualArgs = (command.arguments || []).map(arg => JSON.parse(arg)); - assert.deepEqual(actualArgs, expectedCommand.args || [], "Parsed arguments are not correct"); - - } else { - assert.ok(!command, "Found a command, but expecting to find none"); - return; - } - - if (expectedCommand && expectedCommand.firstErrorText) { - assert.equal((command.errors || []).length > 0, true, "Expected at least one error"); - assert.equal(nonNullProp(command, 'errors')[0].message, expectedCommand.firstErrorText, "First error text was incorrect"); - } else { - assert.equal((command.errors || []).length, 0, "Expected no errors"); - } - } - - testCore(text); - - // Test again with LF changed to CR/LF - const crlfText = text.replace(/\n/g, '\r\n'); - testCore(crlfText); - - // Test again with LF changed to multiple CR/LF - const crlf2Text = text.replace(/\n/g, '\r\n\r\n'); - testCore(crlf2Text); - - // Test again with LF changed to CR - const lfText = text.replace(/\n/g, '\r'); - testCore(lfText); - - // Test again with LF changed to tab - const tabText = text.replace(/\n/g, '\t'); - testCore(tabText); - - // Test again with LF changed to space - const spaceText = text.replace(/\n/g, ' '); - testCore(spaceText); -} - -function wrapInQuotes(word: string, numQuotes: number): string { //0 to do nothing, 1 for single quotes, 2 for double quotes - let result: string; - if (numQuotes === 1) { - result = `'${word}'`; - } else if (numQuotes === 2) { - result = `"${word}"`; - } else { - result = word; - } - return result; -} - -suite("scrapbook parsing Tests", () => { - test("find", () => { - const text = "db.find()"; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test("find with semicolon", () => { - const text = "db.find();"; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test("first of two commands, Mac/Linux", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test("second of two commands, Mac/Linux", () => { - const line1 = "db.find()"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test("second of two commands, Mac/Linux, semicolon", () => { - const line1 = "db.find();"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test("first of two commands, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test("second of two commands, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a':'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - }); - - test("second of two commands, lots of blank lines, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a':'b'})"; - const text = `\r\n\r\n\r\n\r\n\r\n\r\n${line1}\r\n\r\n\r\n\r\n\r\n\r\n${line2}\r\n\r\n\r\n\r\n\r\n\r\n`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(5, 0)); - assert.equal(command.text, line2); - }); - - test("first of two commands, Windows, on blank line before second command", () => { - const line1 = "db.find()"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:1})`; - const text = `${line1}\r\n\r\n\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line1); - } - }); - - test("drop", () => { - testParse( - `db.test.drop()`, - { collection: "test", name: "drop", args: [] }); - }); - - test("find, with empty object argument", () => { - testParse( - `db.test.find({})`, - { collection: "test", name: "find", args: [{}] }); - }); - - test("end-of-line comment", () => { - testParse( - `db.test.drop() // Ignore error "ns not found", it means "test" does not exist yet`, - { collection: "test", name: "drop", args: [] }); - }); - - test("multi-line insert from #214", () => { - for (let q = 0; q <= 2; q++) { - testParse( - `db.heroes.insert({\n${wrapInQuotes("id", q)}: 2,\r\n${wrapInQuotes("name", q)}: "Batman",\r\n\r\n${wrapInQuotes("saying", q)}: "I'm Batman"\r})`, - { - collection: "heroes", name: "insert", args: [ - { - id: 2, - name: "Batman", - saying: "I'm Batman" - } - ] - }); - } - }); - - test("find/project from #214", () => { - testParse( - `db.heroes.find({ "id": 2 }, { "saying": 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - }, - { - saying: 1 - } - ] - }); - }); - - test("extraneous input", () => { - testParse( - `db.heros.find(); - hello there`, - { - collection: "heros", - name: "find", - args: [], - firstErrorText: "mismatched input 'hello' expecting " - } - ); - }); - - test("empty", () => { - testParse( - "// hello there", - undefined - ); - }); - - test("no command found, errors (will be tacked on to a blank command)", () => { - testParse( - "hello there", - { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input 'hello' expecting " - } - ); - }); - - test("expect error: missing comma in arguments", () => { - testParse( - `db.heroes.find({ "id": 2 } { "saying": 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - } - ], - firstErrorText: "mismatched input '{' expecting {',', ')'}" - } - ); - - testParse( - `db.c.find({"a":[1,2,3]"b":1});`, - { - collection: 'c', - name: 'find', - args: [{ a: [1, 2, 3] }], - firstErrorText: "mismatched input '\"b\"' expecting {',', '}'}" - } - ); - - }); - - //https://github.com/Microsoft/vscode-cosmosdb/issues/467 - test("single quoted property names", () => { - testParse( - `db.heroes.find({ 'id': 2 }, { 'saying': 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - }, - { - saying: 1 - } - ] - }); - }); - test("expect error: missing function name", () => { - // From https://github.com/Microsoft/vscode-cosmosdb/issues/659 - testParse( - `db.c1.`, - { - collection: "c1", - name: "", - args: [], - firstErrorText: "mismatched input '' expecting IDENTIFIER" - } - ); - - testParse( - `db.c1.;`, - { - collection: "c1", - name: "", - args: [], - firstErrorText: "mismatched input ';' expecting IDENTIFIER" - } - ); - - testParse( - `db.c1.(1, "a");`, - { - collection: "c1", - name: "", - args: [ - 1, - 'a' - ], - firstErrorText: "missing IDENTIFIER at '('" - } - ); - - testParse( - `..(1, "a");`, - { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input '.' expecting " - } - ); - - // Just make sure doesn't throw - expectSingleCommand(`db..(1, "a");`); - expectSingleCommand(`..c1(1, "a");`); - }); - - test("multi-line insert from #214", () => { - testParse( - `db.heroes.insert({\n"id": 2,\r\n"name": "Batman",\r\n\r\n"saying": "I'm Batman"\r})`, - { - collection: "heroes", name: "insert", args: [ - { - id: 2, - name: "Batman", - saying: "I'm Batman" - } - ] - }); - }); - - test("Array followed by } on separate line, from #73", () => { - testParse( - `db.createUser({ - "user": "buddhi", - "pwd": "123", - "roles": ["readWrite", "dbAdmin"] - } - )`, - { - collection: undefined, - name: "createUser", - args: [ - { - user: "buddhi", - pwd: "123", - roles: ["readWrite", "dbAdmin"] - } - ] - }); - }); - - test("Multiple line arrays, from #489", () => { - testParse( - ` - db.c2.insertMany([ - {"name": "Stephen", "age": 38, "male": true}, - {"name": "Stephen", "age": 38, "male": true} - ]) - `, - { - collection: "c2", - name: "insertMany", - args: [ - [ - { - name: "Stephen", - age: 38, - male: true - }, - { - name: "Stephen", - age: 38, - male: true - } - ] - ] - }); - }); - - test("test function call that has 2 arguments", () => { - const arg0 = `{"Age": 31}`; - const arg1 = `{"Name": true}`; - const text = `db.find(${arg0}\r\n,\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test("test function call with nested parameters - documents in an array", () => { - const arg0 = `[{"name": "a"}, {"name": "b"}, {"name": "c"}]`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0},\r\n\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test("test function call that has a nested parameter", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const text = `db.test1.insertMany(${arg0})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - }); - test("test function call with erroneous syntax: missing comma", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0} ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 61); - }); - test("test function call with erroneous syntax: missing comma, parameters separated with newline", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": \ntrue}`; - const text = `db.test1.insertMany(${arg0} \n ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 1); - assert.deepEqual(err.range.start.character, 2); - }); - test("test function call with erroneous syntax: missing double quote", () => { - const text = `db.test1.insertMany({name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "missing \':\' at '\": {\"'"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 25); - }); - test("test function call with erroneous syntax: missing opening brace", () => { - const text = `db.test1.insertMany("name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input ':' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 26); - }); - - test("Chained command: to use pretty()", () => { - testParse('db.timesheets.find().pretty();', { - collection: "timesheets", - name: "pretty", - args: [] - }); - }); - - test("ISODate with standard date string", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00Z") });', { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: "2018-05-01T00:00:00.000Z" - }, - name: "Stephen" - } - ] - }); - }); - - test("ISODate without Z in date string", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00") });', { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: "2018-05-01T00:00:00.000Z" - }, - name: "Stephen" - } - ] - }); - }); - - test("Invalid ISODate", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00z") });', { - collection: "c1", - name: "insertOne", - args: [], - firstErrorText: "Invalid time value" - }); - }); - - test("Date", () => { - const date: Date = new Date("2018-05-01T00:00:00"); - testParse(`db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": Date("${date.toUTCString()}") });`, { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: date.toString() - }, - name: "Stephen" - } - ] - }); - }); - - test("Keys with periods", () => { - testParse( - `db.timesheets.update( { - "year":"2018", - "month":"06" - },{ - "$set":{ - "workers.0.days.0.something":"yupy!" - } - }); - `, - { - collection: "timesheets", - name: "update", - args: [ - { - year: 2018, - month: "06" - }, - { - $set: { - "workers.0.days.0.something": "yupy!" - } - } - ] - }); - }); - - test("nested objects", () => { - testParse( - `db.users.update({},{ - "$pull":{ - "proposals":{ - "$elemMatch":{"_id":"4qsBHLDCb755c3vPH"} - } - } - })`, - { - collection: "users", - name: "update", - args: [ - {}, - { - $pull: { - proposals: { - $elemMatch: { - _id: "4qsBHLDCb755c3vPH" - } - } - } - } - ] - }); - }); - test("test function call with and without quotes", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.test1.insertMany({${wrapInQuotes("name", q)}: 'First' })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "First" }]); - } - }); - test("test function call with numbers", () => { - const text = `db.test1.insertMany({'name': 1010101})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: 1010101 }]); - }); - test("test function call boolean", () => { - const text = `db.test1.insertMany({'name': false})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: false }]); - }); - test("test function call token inside quotes", () => { - const text = `db.test1.insertMany({'name': 'false'})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "false" }]); - }); - test("test function call with an empty string property value", () => { - const text = `db.test1.insertMany({'name': ''})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "" }]); - }); - test("test function call with array and multiple arguments", () => { - const text = `db.test1.find({'roles': ['readWrite', 'dbAdmin']}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ roles: ["readWrite", "dbAdmin"] }, { resources: ["secondary", "primary"] }]); - }); - test("test function call with nested objects", () => { - const text = `db.test1.find({'roles': [{'optional': 'yes'}]}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ roles: [{ optional: "yes" }] }, { resources: ["secondary", "primary"] }]); - }); - - test("test incomplete function call - replicate user typing - no function call yet", () => { - const text = `db.test1.`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, []); - assert.deepEqual(command.collection, "test1"); - }); - - test("test incomplete function call - replicate user typing - missing propertyValue", () => { - const text = `db.test1.find({"name": {"First" : } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test("test incomplete function call - replicate user typing - missing colon & propertyValue", () => { - const text = `db.test1.find({"name": {"First" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test("test incomplete function call - replicate user typing - empty array as argument", () => { - const text = `db.heroes.aggregate([\n])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [[]]); - }); - - test("test quotes inside a string - 1", () => { - const text = `db.test1.find("That's all")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That's all"]); - }); - - test("test quotes inside a string - 2", () => { - const text = `db.test1.find('That"s all')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That\"s all"]); - }); - - // Note: when escaping a character, escape it twice. - test("test quotes inside a string - 3", () => { - const text = `db.test1.find("Hello \\"there\\"")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ['Hello \\"there\\"']); - }); - - test("test quotes inside a string - 4", () => { - const text = `db.test1.find('Hello \\'there\\'')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["Hello \\'there\\'"]); - }); - - test("test nested property names (has dots in the name)", () => { - const text = `db.test1.find({"name.FirstName": 1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ "name.FirstName": 1 }]); - }); - - test("test managed namespace collection names (has dots in the name)", () => { - const text = `db.test1.beep.find({})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "test1.beep"); - }); - - test("test aggregate query", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.orders.aggregate([ - { ${wrapInQuotes("$match", q)}: { ${wrapInQuotes("status", q)} : "A" } }, - { ${wrapInQuotes("$group", q)}: { ${wrapInQuotes("_id", q)}: "$cust_id", ${wrapInQuotes("total", q)}: { ${wrapInQuotes("$sum", q)}: "$amount" } } }, - { ${wrapInQuotes("$sort", q)}: { ${wrapInQuotes("total", q)}: -1 } } - ], - { - ${wrapInQuotes("cursor", q)}: { ${wrapInQuotes("batchSize", q)}: 0 } - })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "orders"); - assert.deepEqual(command.argumentObjects, [[ - { $match: { status: "A" } }, - { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, - { $sort: { total: -1 } } - ], - { - cursor: { batchSize: 0 } - }]); - } - }); - - test("test ObjectID - no parameter", () => { - const text = `db.c1.insert({"name": ObjectId()})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - assert.ok((nonNullProp(command, 'argumentObjects')[0]).name instanceof ObjectID); - }); - - test("test ObjectID - hex", () => { - const idParam = "abcdef123456789012345678"; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - const id = new ObjectID(idParam); - assert.deepEqual(command.argumentObjects, [{ name: id }]); - }); - - test("test faulty ObjectID - hex - extra characters", () => { - const idParam = "abcdef12345678901234567890"; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const errorMessage = "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, errorMessage); - }); - - test("test faulty ObjectID - hex - fewer characters", () => { - const idParam = "abcdef123456789012345"; - for (let i = 1; i < 3; i++) { - const text = `db.c1.insert({"name": ObjectId(${wrapInQuotes(idParam, i)})})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const errorMessage = "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, errorMessage); - } - }); - //Examples inspired from https://docs.mongodb.com/manual/reference/operator/query/regex/ - test("test regular expressions - only pattern, no flags", () => { - const text = `db.test1.beep.find({ sku: /789$/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, ""); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - pattern and flags", () => { - const text = `db.test1.beep.find({ sku: /789$/i } )`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "i"); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - Intellisense - flag contains invalid option", () => { - const text = `db.test1.beep.find({ sku: /789$/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - const err = parseError(error); - assert.deepEqual("Unexpected node encountered", err.message); - } - }); - - test("test regular expressions - wrong escape - throw error", () => { - const text = `db.test1.beep.find({ sku: /789$\\/b\\/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - assert.equal(error.message, "Invalid regular expression: /789$\\/b\\/: \\ at end of pattern"); - } - }); - - //Passing the following test should imply the rest of the tests pass too. - // The regex parsing tests following this test should help zero-in on which case isn't handled properly. - test("test regular expression parsing - with many special cases", () => { - const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"); - }); - - test("test regular expression parsing EJSON syntax - with many special cases", () => { - const text = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"); - }); - - test("test regular expression parsing interoperability", () => { - const text1 = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"]); - }); - - test("test regular expression parsing interoperability - word break", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\b/g })`; // equivalent to user typing out /ker\b/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\b", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\b"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\b"]); - }); - - test("test regular expression parsing interoperability - newline", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\n/g })`; // equivalent to user typing out /ker\n/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\n", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\n"]); - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\n"]); - }); - test("test regular expression parsing interoperability - carriage return", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\r/g })`; // equivalent to user typing out /ker\r/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\r", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\r"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\r"]); - }); - - test("test regular expressions - only pattern, no flags", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, ""); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - pattern and flags", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"i" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "i"); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - Intellisense - flag contains invalid option", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"q" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, "Invalid flags supplied to RegExp constructor 'q'"); - assert.deepEqual(nonNullProp(command, 'errors')[0].range.start.character, 19); - }); - - test("test regular expression parsing - with groupings", () => { - const text = `db.test1.beep.find({ sku: /(?:hello)\\3/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(?:hello)\\3"); - }); - - test("test regular expression parsing - with special characters", () => { - const text = `db.test1.beep.find({ sku: /(hello)*(world)?(name)+./g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello)*(world)?(name)+."); - }); - - test("test regular expression parsing - with boundaries", () => { - const text = `db.test1.beep.find({ sku: /^(hello world)[^0-9]|(world\\b)$/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello world)[^0-9]|(world\\b)$"); - }); - - test("test regular expression parsing - with quantifiers", () => { - const text = `db.test1.beep.find({ sku: /(hello)*[^0-9]+|(world){0,2}./g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello)*[^0-9]+|(world){0,2}."); - }); - - test("test regular expression parsing - with conditional", () => { - const text = `db.test1.beep.find({ sku: /(hello?= world)|(world)/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello?= world)|(world)"); - }); - - test("test regular expression parsing - with escaped special characters", () => { - const text = `db.test1.beep.find({ sku: /world\\*\\.\\?\\+/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "world\\*\\.\\?\\+"); - }); - - test("test chained command: argument aggregation", () => { - testParse('db.timesheets.find({name: "Andy", surname: "Jackson"}).pretty();', { - collection: "timesheets", - name: "pretty", - args: [{ name: "Andy", surname: "Jackson" }] - }); - }); - - test("Chained command - order of parsed arguments", () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1}).skip(40);', { - collection: "timesheets", - name: "skip", - args: [{ name: "Andy" }, { age: 1 }, 40] - }); - }); - - test("Chained command - missing period", () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1})skip(40);', { - collection: "timesheets", - name: "sort", - args: [{ name: "Andy" }, { age: 1 }], - firstErrorText: "mismatched input 'skip' expecting " - }); - }); - - test("Chained command - mid-type - missing bracket", () => { - testParse('db.timesheets.find({name:"Andy"}).sort', { - collection: "timesheets", - name: "sort", - args: [{ name: "Andy" }], - firstErrorText: "mismatched input '' expecting '('" - }); - }); - - test("Chained command - mid-type - typed the dot, but not the function call", () => { - testParse('db.timesheets.find({name:"Andy"}).', { - collection: "timesheets", - name: "", - args: [{ name: "Andy" }], - firstErrorText: "mismatched input '' expecting IDENTIFIER" - }); - }); - - //TODO: Tests to simulate cases where the user hasn't completed typing - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/688", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.hdr.aggregate([ - { ${wrapInQuotes("$match", q)}: { "CURRENCY_ID": "USD" } }, - ])`; //Note the trailing comma. There should be 1 argument object returned, an array, that has 2 elements - //one expected, and another empty object. - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "hdr"); - assert.deepEqual(command.argumentObjects, [[{ $match: { CURRENCY_ID: "USD" } }, {}]]); - } - }); - - test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/785", () => { - testParse('db.timesheets.find({name:"Andy"}).count();', { - collection: "timesheets", - name: "count", - args: [{ name: "Andy" }] - }); - }); - - test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/795", () => { - testParse('db.timesheets.find({}).limit(10);', { - collection: "timesheets", - name: "limit", - args: [{}, 10] - }); - }); - - test("Chained command alternative for rs.slaveOk()- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/565", () => { - testParse('db.getMongo().setSlaveOk();', { - collection: "", - name: "setSlaveOk", - args: [] - }); - }); - - test("Multiple line command, from #489", () => { - testParse( - ` - db.finalists.find({name: "Jefferson"}) - . - limit - (10); - `, - { - collection: "finalists", - name: "limit", - args: [ - { - name: "Jefferson" - }, - 10 - ] - }); - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/703", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({ ${wrapInQuotes("user", q)}: { ${wrapInQuotes("$in", q)}: [ "A80", "HPA" ] } },{ ${wrapInQuotes("_id", q)}: false });`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "Users"); - assert.deepEqual(command.argumentObjects, [{ user: { $in: ["A80", "HPA"] } }, { _id: false }]); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/691", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.users.aggregate([ - { ${wrapInQuotes("$match", q)}: {${wrapInQuotes("_id", q)}: {"$oid" :"5b23d2ba92b52cf794bdeb9c")}}}, - { ${wrapInQuotes("$project", q)}: { - ${wrapInQuotes("scores", q)}: {${wrapInQuotes("$filter", q)}: { - ${wrapInQuotes("input", q)}: '$scores', - ${wrapInQuotes("as", q)}: 'score', - ${wrapInQuotes("cond", q)}: {${wrapInQuotes("$gt", q)}: ['$$score', 3]} - }} - }} - ])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "users"); - assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][0], { $match: { _id: new ObjectId("5b23d2ba92b52cf794bdeb9c") } }); - assert.deepEqual( - nonNullProp(command, 'argumentObjects')[0][1], - { - $project: { - scores: { - $filter: { - input: '$scores', - as: 'score', - cond: { $gt: ['$$score', 3] } - } - } - } - }); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/717", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({${wrapInQuotes("age", q)} : { ${wrapInQuotes("$in", q)} : [19, 20, 22, 25]}});`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "Users"); - assert.deepEqual(command.argumentObjects, [{ age: { $in: [19, 20, 22, 25] } }]); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/737", () => { - const text = `db.c1.insert({},f)`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{}, {}]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, "mismatched input 'f' expecting {'{', '[', RegexLiteral, StringLiteral, 'null', BooleanLiteral, NumericLiteral}"); - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/899 - multi-line comment, not regex", () => { - for (const escape of ['\n', '\r', '\n\r', '\r\n']) { - const text = `db.heroes.count()${escape}/*db.c2.insertMany([${escape}{"name": "Stephen", "age": 38, "male": true},${escape}{"name": "Stephen", "age": 38, "male": true}${escape}]);${escape}*/${escape}${escape}db.heroes.find();`; - const commands = getAllCommandsFromText(text); - assert.equal(commands.length, 2, `Error in parsing ${text}`); - assert.equal(commands[0].name, "count"); - assert.equal(commands[1].name, "find"); - } - }); -}); diff --git a/test/mongoShell.test.ts b/test/mongoShell.test.ts deleted file mode 100644 index 83fdb845e..000000000 --- a/test/mongoShell.test.ts +++ /dev/null @@ -1,288 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// CONSIDER: Run in pipeline -import * as assert from 'assert'; -import * as cp from "child_process"; -import * as fse from 'fs-extra'; -import * as os from 'os'; -import * as path from 'path'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { ext, IDisposable, isWindows, MongoShell, parseError } from '../extension.bundle'; -import { runWithSetting } from './runWithSetting'; -import { setEnvironmentVariables } from './util/setEnvironmentVariables'; - -const VERBOSE = false; // If true, the output from the Mongo server and shell will be sent to the console for debugging purposes - -let testsSupported: boolean = true; - -if (!isWindows) { - // CONSIDER: Non-Windows - console.warn(`Not running in Windows - skipping MongoShell tests`); - testsSupported = false; -} - -suite("MongoShell", async function (this: Mocha.Suite): Promise { - // https://github.com/mochajs/mocha/issues/2025 - this.timeout(10000); - - async function testIfSupported(title: string, fn?: Mocha.Func | Mocha.AsyncFunc): Promise { - await runWithSetting(ext.settingsKeys.mongoShellTimeout, '60', async () => { - if (testsSupported) { - test(title, fn); - } else { - test(title); - } - }); - } - - // CONSIDER: Make more generic - let mongodCP: cp.ChildProcess; - const mongodPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongod.exe"; - const mongoPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongo.exe"; - let mongoDOutput = ""; - let mongoDErrors = ""; - let isClosed = false; - - if (!fse.existsSync(mongodPath)) { - console.log(`Couldn't find mongod.exe at ${mongodPath} - skipping MongoShell tests`); - testsSupported = false; - } else if (!fse.existsSync(mongodPath)) { - console.log(`Couldn't find mongo.exe at ${mongoPath} - skipping MongoShell tests`); - testsSupported = false; - } else { - // Prevent code 100 error: https://stackoverflow.com/questions/41420466/mongodb-shuts-down-with-code-100 - await fse.ensureDir('D:\\data\\db\\'); - } - - class FakeOutputChannel implements vscode.OutputChannel { - public name: string; - public output: string; - - public append(value: string): void { - assert(value !== undefined); - assert(!value.includes('undefined')); - this.output = this.output ? this.output + os.EOL + value : value; - log(value, "Output channel: "); - } - public appendLine(value: string): void { - assert(value !== undefined); - this.append(value + os.EOL); - } - public clear(): void { } - public show(preserveFocus?: boolean): void; - public show(column?: vscode.ViewColumn, preserveFocus?: boolean): void; - public show(_column?: any, _preserveFocus?: any): void { } - public hide(): void { } - public dispose(): void { } - public replace(_value: string): void { } - } - - function log(text: string, linePrefix: string): void { - text = text.replace(/(^|[\r\n]+)/g, "$1" + linePrefix); - if (VERBOSE) { - console.log(text); - } - } - - async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); - } - - function executeInShell(command: string): string { - return cp.execSync(command, {}).toString(); - } - - suiteSetup(() => { - if (testsSupported) { - assert(fse.existsSync(mongodPath), "Couldn't find mongod.exe at " + mongodPath); - assert(fse.existsSync(mongoPath), "Couldn't find mongo.exe at " + mongoPath); - - // Shut down any still-running mongo server - try { - executeInShell('taskkill /f /im mongod.exe'); - } catch (error) { - assert(/The process .* not found/.test(parseError(error).message), `Error killing mongod: ${parseError(error).message}`); - } - - mongodCP = cp.spawn(mongodPath, ['--quiet']); - - mongodCP.stdout?.on("data", (buffer: Buffer) => { - log(buffer.toString(), "mongo server: "); - mongoDOutput += buffer.toString(); - }); - mongodCP.stderr?.on("data", (buffer: Buffer) => { - log(buffer.toString(), "mongo server STDERR: "); - mongoDErrors += buffer.toString(); - }); - mongodCP.on("error", (error: unknown) => { - log(parseError(error).message, "mongo server Error: "); - mongoDErrors += parseError(error).message + os.EOL; - }); - mongodCP.on("close", (code?: number) => { - console.log(`mongo server: Close code=${code}`); - isClosed = true; - if (isNumber(code) && code !== 0) { - mongoDErrors += `mongo server: Closed with code "${code}"${os.EOL}`; - } - }); - } - }); - - suiteTeardown(() => { - if (mongodCP) { - mongodCP.kill(); - } - }); - - await testIfSupported("Verify mongod running", async () => { - while (!mongoDOutput.includes('waiting for connections on port 27017')) { - assert.equal(mongoDErrors, "", "Expected no errors"); - assert(!isClosed); - await delay(50); - } - }); - - async function testShellCommand(options: { - script: string; - expectedResult?: string; - expectedError?: string | RegExp; - expectedOutput?: RegExp; - title?: string; // Defaults to script - args?: string[]; // Defaults to [] - mongoPath?: string; // Defaults to the correct mongo path - env?: { [key: string]: string }; // Add to environment - timeoutSeconds?: number; - }): Promise { - await testIfSupported(options.title || options.script, async () => { - assert(!isClosed); - assert(mongoDErrors === ""); - - let previousEnv: IDisposable | undefined; - let shell: MongoShell | undefined; - const outputChannel = new FakeOutputChannel(); - - try { - previousEnv = setEnvironmentVariables(options.env || {}); - shell = await MongoShell.create(options.mongoPath || mongoPath, options.args || [], '', false, outputChannel, options.timeoutSeconds || 5); - const result = await shell.executeScript(options.script); - if (options.expectedError) { - assert(false, `Expected error did not occur: '${options.expectedError}'`); - } - if (options.expectedResult !== undefined) { - assert.equal(result, options.expectedResult); - } - } catch (error) { - const message = parseError(error).message; - - if (options.expectedError instanceof RegExp) { - assert(options.expectedError.test(message), `Actual error did not match expected error regex. Actual error: ${message}`); - } else if (typeof options.expectedError === 'string') { - assert.equal(message, options.expectedError); - } else { - assert(false, `Unexpected error during the test: ${message}`); - } - - if (options.expectedOutput instanceof RegExp) { - assert(options.expectedOutput.test(outputChannel.output), `Actual contents written to output channel did not match expected regex. Actual output channel contents: ${outputChannel.output}`); - } - } finally { - if (shell) { - shell.dispose(); - } - if (previousEnv) { - previousEnv.dispose(); - } - } - }); - } - - await testShellCommand({ - script: 'use abc', - expectedResult: 'switched to db abc' - }); - - await testShellCommand({ - title: "Incorrect path", - script: 'use abc', - mongoPath: "/notfound/mongo.exe", - expectedError: /Could not find .*notfound.*mongo.exe/ - }); - - await testShellCommand({ - title: "Find mongo through PATH", - script: 'use abc', - mongoPath: "mongo", - expectedResult: 'switched to db abc', - env: { - PATH: process.env.path! + ";" + path.dirname(mongoPath) - } - }); - - await testShellCommand({ - title: "With valid argument", - script: 'use abc', - args: ["--quiet"], - expectedResult: 'switched to db abc' - }); - - await testShellCommand({ - title: "With invalid argument", - script: '', - args: ["--hey-man-how-are-you"], - expectedError: /Error parsing command line: unrecognised option/ - }); - - await testShellCommand({ - title: "Output window may contain additional information", - script: '', - args: ["-u", "baduser", "-p", "badpassword"], - expectedError: /The output window may contain additional information/ - }); - - await testShellCommand({ - title: "With bad credentials", - script: '', - args: ["-u", "baduser", "-p", "badpassword"], - expectedError: /The process exited with code 1/, - expectedOutput: /Authentication failed/ - }); - - await testShellCommand({ - title: "Process exits immediately", - script: '', - args: ["--version"], - expectedError: /The process exited prematurely/ - }); - - await testShellCommand({ - title: "Javascript", - script: "for (var i = 0; i < 123; ++i) { }; i", - expectedResult: "123" - }); - - await testShellCommand({ - title: "Actual timeout", - script: "for (var i = 0; i < 10000000; ++i) { }; i", - expectedError: /Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting./, - timeoutSeconds: 2 - }); - - await testIfSupported("More results than displayed (type 'it' for more -> (More))", async () => { - const shell = await MongoShell.create(mongoPath, [], '', false, new FakeOutputChannel(), 5); - await shell.executeScript('db.mongoShellTest.drop()'); - await shell.executeScript('for (var i = 0; i < 50; ++i) { db.mongoShellTest.insert({a:i}); }'); - - const result = await shell.executeScript('db.mongoShellTest.find().pretty()'); - - assert(!result.includes('Type "it" for more')); - assert(result.includes('(More)')); - - shell.dispose(); - }); -}); diff --git a/test/postgresConnectionStrings.test.ts b/test/postgresConnectionStrings.test.ts deleted file mode 100644 index 3f2ed8da4..000000000 --- a/test/postgresConnectionStrings.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { addDatabaseToConnectionString } from '../extension.bundle'; - -function testAddDatabaseToConectionString(connectionString: string, databaseName: string, expectedConnectionString: string | undefined): void { - const modifiedConnectionString = addDatabaseToConnectionString(connectionString, databaseName); - assert.equal(modifiedConnectionString, expectedConnectionString); -} - -suite(`postgresConnectionStrings`, () => { - test(`addDatabaseToConnectionString`, () => { - // Connection strings follow the following format (https://www.postgresql.org/docs/12/libpq-connect.html): - // postgres://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/`, 'testdb', 'postgres://user:password@test:5432/testdb'); - testAddDatabaseToConectionString(`postgres://user:password@test:5432/testdb`, 'testdb2', `postgres://user:password@test:5432/testdb2`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432`, 'testdb', 'postgres://user:password@test:5432/testdb'); - testAddDatabaseToConectionString(`postgres://user:password@test:5432/?ssl=true&sslmode=require`, 'testdb', `postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`, 'testdb2', `postgres://user:password@test:5432/testdb2?ssl=true&sslmode=require`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/`, `test%20`, `postgres://user:password@test:5432/test%2520`); - - }); -}); diff --git a/test/runTest.ts b/test/runTest.ts deleted file mode 100644 index f4fe5eb12..000000000 --- a/test/runTest.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron'; -import * as cp from 'child_process'; -import * as path from 'path'; - -async function main(): Promise { - try { - const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); - const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - - cp.spawnSync( - cli, - [ - ...args, - '--install-extension', 'ms-vscode.azure-account', - '--install-extension', 'ms-azuretools.vscode-azureresourcegroups', - ], - { - encoding: 'utf-8', - stdio: 'inherit' - }); - - const repoRoot: string = path.resolve(__dirname, '..', '..'); - await runTests({ - vscodeExecutablePath, - extensionDevelopmentPath: repoRoot, - launchArgs: [ - path.resolve(repoRoot, 'test', 'test.code-workspace'), - '--disable-workspace-trust' - ], - extensionTestsPath: path.resolve(repoRoot, 'dist', 'test', 'index'), - extensionTestsEnv: { - DEBUGTELEMETRY: 'v' - } - }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -void main(); diff --git a/test/runWithSetting.ts b/test/runWithSetting.ts deleted file mode 100644 index 7c095ace6..000000000 --- a/test/runWithSetting.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext, getGlobalSetting, updateGlobalSetting } from "../extension.bundle"; - -export async function runWithDatabasesSetting(key: string, value: string | boolean | undefined, callback: () => Promise): Promise { - await runWithSettingInternal(key, value, ext.prefix, callback); -} - -export async function runWithSetting(key: string, value: string | boolean | undefined, callback: () => Promise): Promise { - await runWithSettingInternal(key, value, '', callback); -} - -async function runWithSettingInternal(key: string, value: string | boolean | undefined, prefix: string, callback: () => Promise): Promise { - const oldValue: string | boolean | undefined = getGlobalSetting(key, prefix); - try { - await updateGlobalSetting(key, value, prefix); - await callback(); - } finally { - await updateGlobalSetting(key, oldValue, prefix); - } -} diff --git a/test/test.code-workspace b/test/test.code-workspace deleted file mode 100644 index d1d77c70e..000000000 --- a/test/test.code-workspace +++ /dev/null @@ -1,8 +0,0 @@ -{ - "folders": [ - { - "path": "../testWorkspace" - } - ], - "settings": {} -} diff --git a/test/timeout.test.ts b/test/timeout.test.ts deleted file mode 100644 index f155a5cb4..000000000 --- a/test/timeout.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { rejectOnTimeout, valueOnTimeout } from '../extension.bundle'; - -suite("timeout Tests", () => { - suite("rejectOnTimeout", () => { - - test("executes synchronously", async () => { - let executed: boolean = false; - - await rejectOnTimeout(1, () => { - executed = true; - }); - - assert.equal(executed, true); - }); - - test("executes synchronously in promise", async () => { - let executed = false; - - await rejectOnTimeout(1, () => { - return new Promise((resolve, _reject) => { - executed = true; - resolve(); - }); - }); - - assert.equal(executed, true); - }); - - test("executes asynchnously before time-out", async () => { - let executed = false; - - await rejectOnTimeout(1000, () => { - return new Promise((resolve, _reject) => { - setTimeout(() => { executed = true; resolve(); }, 1); - }); - }); - assert.equal(executed, true); - }); - - test("timed out", async () => { - let executed = false; - - try { - await rejectOnTimeout(1, async () => { - await new Promise((resolve, _reject) => { - setTimeout(() => { executed = true; resolve(); }, 1000); - }); - }); - - assert.fail(null, null, "Expected exception"); - } catch (error) { - } - - assert.equal(executed, false); - }); - - test("throws before time-out", async () => { - const executed = false; - let error: Error = new Error("I haven't thrown up yet"); - - try { - await rejectOnTimeout(1000, async () => { - await new Promise((_resolve, _reject) => { - throw new Error("I threw up"); - }); - }); - } catch (err) { - error = err; - } - - assert.equal(executed, false); - assert.equal(error.message, "I threw up"); - }); - }); - - suite("valueOnTimeout", () => { - - test("executed", async () => { - const value = await valueOnTimeout(1000, 123, async () => { - return await new Promise((resolve, _reject) => { - setTimeout(() => { resolve(-123); }, 1); - }); - }); - - assert.equal(value, -123); - }); - - test("timed out", async () => { - const value = await valueOnTimeout(1, 123, async () => { - return await new Promise((resolve, _reject) => { - setTimeout(() => { resolve(-123); }, 1000); - }); - }); - - assert.equal(value, 123); - }); - - test("reject", async () => { - let error; - try { - await valueOnTimeout(1000, 123, async () => { - return await new Promise((_resolve, reject) => { - setTimeout(() => { reject(new Error("rejected")); }, 1); - }); - }); - } catch (err) { - error = err; - } - - assert.equal(error && error.message, "rejected"); - }); - }); - -}); diff --git a/test/unit/DocDBUtils.test.ts b/test/unit/DocDBUtils.test.ts deleted file mode 100644 index 0fafd95cf..000000000 --- a/test/unit/DocDBUtils.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { describe, it } from 'mocha'; -import { sanitizeId } from "../../src/docdb/tree/DocDBUtils"; - -describe("DocDBUtils", function () { - it("Replaces + with whitespace", function () { - const id = "a+b+c"; - const sanitizedId = sanitizeId(id); - assert.strictEqual(sanitizedId, "a b c"); - }); -}); diff --git a/test/unit/getClientConfig.test.ts b/test/unit/getClientConfig.test.ts deleted file mode 100644 index 33f8883e1..000000000 --- a/test/unit/getClientConfig.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { describe, it } from 'mocha'; -import { postgresDefaultPort } from '../../src/constants'; -import { PostgresServerType } from '../../src/postgres/abstract/models'; -import { getClientConfigs } from '../../src/postgres/getClientConfig'; -import { ParsedPostgresConnectionString } from '../../src/postgres/postgresConnectionStrings'; - -describe("getClientConfig Tests", () => { - describe("in subscription", () => { - it("Password only", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - user: "fake_user", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - // Cannot test null/undefined host because if it is the case, the code has thrown much earlier when constructing the ParsedPostgresConnectionString object. - - it("Password only - Missing port", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - user: "fake_user", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - assert(clientConfigs.password?.port === parseInt(postgresDefaultPort), "Should fallback to default port"); - }); - - it("Password only - missing username", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("No credential", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - user: "fake_user", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad only - Flexible server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Flexible, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd !== undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad and password - Flexible server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database", - user: "fake_user", - password: "fake_password", - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Flexible, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd !== undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad only - Single server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Single, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - }); - - describe("in attachment", () => { - it("Connection string only", async () => { - const rawConnectionString = "postgres://fake_connection_string"; - const parsedConnectionString = new ParsedPostgresConnectionString( - rawConnectionString, - { - host: "fake_host", - database: null - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, false, databaseName); - assert(clientConfigs.connectionString !== undefined); - }); - }); -}); diff --git a/test/util/getIp.test.ts b/test/util/getIp.test.ts deleted file mode 100644 index 3e2b0cbc1..000000000 --- a/test/util/getIp.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { createTestActionContext } from '@microsoft/vscode-azext-dev'; -import * as assert from 'assert'; -import { isIPv4 } from 'net'; -import { getPublicIpv4, isIpInRanges } from '../../extension.bundle'; - -suite("getPublicIpv4", () => { - test("get IP", async () => { - try { - const context = await createTestActionContext(); - const ip = await getPublicIpv4(context); - assert(isIPv4(ip), "IP address isn't v4"); - } catch (error) { - assert(false, error.message ?? "Fail to get IP address"); - } - }); -}); - -suite("isIpInRanges", function () { - const ip = "12.34.56.78"; - test("Includes ip at start", function () { - const ranges = [{ startIpAddress: "12.34.56.78", endIpAddress: "12.34.56.80" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Includes ip at end", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.78" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Includes ip in range", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.80" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Excludes ip before start", function () { - const ranges = [{ startIpAddress: "12.34.56.80", endIpAddress: "12.34.56.80" }]; - assert(!isIpInRanges(ip, ranges)); - }); - test("Excludes ip after end", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.76" }]; - assert(!isIpInRanges(ip, ranges)); - }); -}); diff --git a/test/util/setEnvironmentVariables.test.ts b/test/util/setEnvironmentVariables.test.ts deleted file mode 100644 index 333a6803b..000000000 --- a/test/util/setEnvironmentVariables.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { isWindows } from '../../extension.bundle'; -import { setEnvironmentVariables } from './setEnvironmentVariables'; - -suite("setEnvironmentVariables (test util)", () => { - test("restore", () => { - const currentPath = process.env.PATH; - const dispose = setEnvironmentVariables({ PATH: "new path" }); - - assert.equal(process.env.PATH, 'new path'); - - dispose.dispose(); - - assert.equal(process.env.PATH, currentPath); - }); - - test("different casings (Windows)", () => { - if (isWindows) { - const currentPath = process.env.paTH; - const dispose = setEnvironmentVariables({ PAth: "new path" }); - - assert.equal(process.env.path, 'new path'); - assert.equal(process.env.PATH, 'new path'); - - dispose.dispose(); - - assert.equal(process.env.path, currentPath); - assert.equal(process.env.PATH, currentPath); - } - }); -}); diff --git a/test/util/setEnvironmentVariables.ts b/test/util/setEnvironmentVariables.ts deleted file mode 100644 index 7dc468729..000000000 --- a/test/util/setEnvironmentVariables.ts +++ /dev/null @@ -1,35 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IDisposable } from "../../extension.bundle"; - -/** - * Add a set of environment variables, and return to the previous values after disposing the result - */ -export function setEnvironmentVariables(env: { [key: string]: string }): IDisposable { - const setRestoreEnv = new SetRestoreEnv(); - setRestoreEnv.set(env); - return setRestoreEnv; -} - -class SetRestoreEnv implements IDisposable { - private _previousValues: { [key: string]: string } = {}; - - public set(env: { [key: string]: string }): void { - for (const key of Object.keys(env || {})) { - [this._previousValues[key], process.env[key]] = [process.env[key]!, env[key]]; - } - } - - public restore(): void { - for (const key of Object.keys(this._previousValues)) { - process.env[key] = this._previousValues[key]; - } - } - - public dispose(): void { - this.restore(); - } -} diff --git a/test/wrapError.test.ts b/test/wrapError.test.ts deleted file mode 100644 index 3663aa7ee..000000000 --- a/test/wrapError.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import * as os from 'os'; -import { wrapError } from '../extension.bundle'; - -suite("wrapError", () => { - test("just outer string", () => { - const wrapped = wrapError('Outer error'); - assert(typeof wrapped === 'string'); - assert.equal(wrapped, 'Outer error'); - }); - - test("just outer error", () => { - const wrapped = wrapError(new Error('Outer error')); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, 'Outer error'); - }); - - test("just inner", () => { - const wrapped = wrapError(undefined, 'Inner error'); - assert(typeof wrapped === 'string'); - assert.equal(wrapped, 'Inner error'); - }); - - test("outer string, inner string", () => { - const wrapped = wrapError('Outer error.', 'Inner error.'); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer error, inner string", () => { - const wrapped = wrapError(new Error('Outer error.'), 'Inner error.'); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer error, inner error", () => { - const wrapped = wrapError(new Error('Outer error.'), new Error('Inner error.')); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer string, inner error", () => { - const wrapped = wrapError('Outer error.', new Error('Inner error.')); - assert(wrapped instanceof Error); - assert(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); -}); From 06c738bec587c6870e194714a9624d0ec0864eb0 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Fri, 17 Nov 2023 16:23:58 +0200 Subject: [PATCH 16/33] squash! --- CHANGELOG.md | 619 +- CODE_OF_CONDUCT.md | 10 +- LICENSE.md | 42 +- NOTICE.html | 6617 +++++++++------ README.md | 208 +- SECURITY.md | 56 +- SUPPORT.md | 3 +- Source/AzureDBExperiences.ts | 250 +- Source/DatabasesFileSystem.ts | 147 +- Source/ParsedConnectionString.ts | 36 +- Source/azureAccountUtils.ts | 27 +- .../api/DatabaseAccountTreeItemInternal.ts | 220 +- .../commands/api/DatabaseTreeItemInternal.ts | 93 +- Source/commands/api/apiCache.ts | 82 +- Source/commands/api/findTreeItem.ts | 355 +- Source/commands/api/pickTreeItem.ts | 220 +- Source/commands/api/revealTreeItem.ts | 29 +- .../DatabaseAccountDeleteStep.ts | 14 +- .../IDeleteWizardContext.ts | 25 +- .../deleteCosmosDBAccount.ts | 69 +- .../deleteDatabaseAccount.ts | 60 +- Source/commands/importDocuments.ts | 328 +- Source/constants.ts | 133 +- Source/docdb/docDBConnectionStrings.ts | 78 +- Source/docdb/getCosmosClient.ts | 35 +- Source/docdb/registerDocDBCommands.ts | 238 +- Source/docdb/tree/DocDBAccountTreeItem.ts | 56 +- Source/docdb/tree/DocDBAccountTreeItemBase.ts | 188 +- Source/docdb/tree/DocDBCollectionTreeItem.ts | 187 +- Source/docdb/tree/DocDBDatabaseTreeItem.ts | 31 +- .../docdb/tree/DocDBDatabaseTreeItemBase.ts | 329 +- Source/docdb/tree/DocDBDocumentTreeItem.ts | 286 +- Source/docdb/tree/DocDBDocumentsTreeItem.ts | 269 +- .../tree/DocDBStoredProcedureTreeItem.ts | 134 +- .../tree/DocDBStoredProceduresTreeItem.ts | 216 +- Source/docdb/tree/DocDBTreeItemBase.ts | 79 +- Source/docdb/tree/DocDBUtils.ts | 2 +- Source/docdb/tree/IDocDBTreeRoot.ts | 9 +- Source/extension.ts | 592 +- Source/extensionVariables.ts | 61 +- Source/getExtensionApi.ts | 41 +- Source/graph/gremlinEndpoints.ts | 74 +- Source/graph/registerGraphCommands.ts | 125 +- Source/graph/tree/GraphAccountTreeItem.ts | 87 +- Source/graph/tree/GraphCollectionTreeItem.ts | 181 +- Source/graph/tree/GraphDatabaseTreeItem.ts | 109 +- Source/graph/tree/GraphTreeItem.ts | 105 +- Source/mongo/MongoCommand.ts | 26 +- Source/mongo/MongoScrapbook.ts | 1135 ++- Source/mongo/MongoShell.ts | 353 +- Source/mongo/connectToMongoClient.ts | 87 +- Source/mongo/errorListeners.ts | 98 +- Source/mongo/grammar/mongoLexer.ts | 535 +- Source/mongo/grammar/mongoListener.ts | 36 +- Source/mongo/grammar/mongoParser.ts | 2994 +++---- Source/mongo/grammar/mongoVisitor.ts | 32 +- Source/mongo/grammar/visitors.ts | 157 +- Source/mongo/languageClient.ts | 120 +- Source/mongo/languageServer.ts | 4 +- Source/mongo/mongoConnectionStrings.ts | 158 +- Source/mongo/registerMongoCommands.ts | 500 +- Source/mongo/services/IConnectionParams.ts | 6 +- .../mongo/services/MongoCodeLensProvider.ts | 130 +- .../mongo/services/completionItemProvider.ts | 1015 ++- Source/mongo/services/languageService.ts | 193 +- Source/mongo/services/mongoScript.ts | 195 +- Source/mongo/services/schemaService.ts | 1336 +-- Source/mongo/setConnectedNode.ts | 10 +- Source/mongo/tree/IMongoTreeRoot.ts | 3 +- Source/mongo/tree/MongoAccountTreeItem.ts | 307 +- Source/mongo/tree/MongoCollectionTreeItem.ts | 753 +- Source/mongo/tree/MongoDatabaseTreeItem.ts | 611 +- Source/mongo/tree/MongoDocumentTreeItem.ts | 182 +- .../abstract/AbstractPostgresClient.ts | 30 +- Source/postgres/abstract/models.ts | 73 +- .../postgres/commands/checkAuthentication.ts | 56 +- .../commands/configurePostgresFirewall.ts | 128 +- .../commands/connectPostgresDatabase.ts | 70 +- .../postgres/commands/copyConnectionString.ts | 76 +- .../commands/createPostgresDatabase.ts | 49 +- .../IPostgresQueryWizardContext.ts | 5 +- .../runPostgresQueryWizard.ts | 29 +- .../createPostgresQuery/validateIdentifier.ts | 203 +- .../IPostgresServerWizardContext.ts | 34 +- .../commands/deletePostgresDatabase.ts | 61 +- .../commands/deletePostgresFunction.ts | 57 +- .../postgres/commands/deletePostgresServer.ts | 37 +- .../commands/deletePostgresStoredProcedure.ts | 60 +- .../postgres/commands/deletePostgresTable.ts | 56 +- .../commands/enterPostgresCredentials.ts | 153 +- .../executePostgresQueryInDocument.ts | 127 +- .../postgres/commands/openPostgresFunction.ts | 23 +- .../commands/openPostgresStoredProcedure.ts | 24 +- .../commands/registerPostgresCommands.ts | 166 +- .../commands/setPostgresCredentials.ts | 44 +- Source/postgres/getClientConfig.ts | 187 +- .../postgres/getPostgresProcedureQueryRows.ts | 61 +- Source/postgres/getTables.ts | 34 +- Source/postgres/postgresConnectionStrings.ts | 123 +- Source/postgres/postgresConstants.ts | 6 +- Source/postgres/runPostgresQuery.ts | 21 +- .../services/PostgresCodeLensProvider.ts | 122 +- Source/postgres/showPostgresQuery.ts | 16 +- Source/postgres/tree/ClientConfigFactory.ts | 171 +- .../postgres/tree/PostgresColumnTreeItem.ts | 41 +- .../postgres/tree/PostgresDatabaseTreeItem.ts | 252 +- .../postgres/tree/PostgresFunctionTreeItem.ts | 70 +- .../tree/PostgresFunctionsTreeItem.ts | 70 +- .../tree/PostgresResourcesTreeItemBase.ts | 26 +- .../postgres/tree/PostgresServerTreeItem.ts | 611 +- .../tree/PostgresStoredProcedureTreeItem.ts | 68 +- .../tree/PostgresStoredProceduresTreeItem.ts | 74 +- Source/postgres/tree/PostgresTableTreeItem.ts | 92 +- .../postgres/tree/PostgresTablesTreeItem.ts | 81 +- Source/resolver/AppResolver.ts | 149 +- Source/resolver/DatabaseWorkspaceProvider.ts | 48 +- .../ResolvedDatabaseAccountResource.ts | 117 +- .../resolver/ResolvedDocDBAccountResource.ts | 63 +- .../resolver/ResolvedMongoAccountResource.ts | 22 +- .../ResolvedPostgresServerResource.ts | 79 +- Source/table/tree/TableAccountTreeItem.ts | 50 +- Source/tree/AttachedAccountsTreeItem.ts | 973 ++- .../tree/AzureAccountTreeItemWithAttached.ts | 65 +- Source/tree/AzureDBAPIStep.ts | 159 +- .../CosmosDBAccountCapacityStep.ts | 73 +- .../CosmosDBAccountCreateStep.ts | 130 +- .../CosmosDBAccountNameStep.ts | 85 +- .../ICosmosDBWizardContext.ts | 24 +- Source/tree/IAzureDBWizardContext.ts | 10 +- Source/tree/SubscriptionTreeItem.ts | 460 +- Source/utils/InteractiveChildProcess.ts | 336 +- Source/utils/activityUtils.ts | 13 +- Source/utils/array.ts | 18 +- Source/utils/azureClients.ts | 39 +- Source/utils/azureUtils.ts | 12 +- Source/utils/cp.ts | 17 +- Source/utils/getIp.ts | 106 +- Source/utils/getSecretStorageKey.ts | 2 +- Source/utils/improveError.ts | 14 +- Source/utils/localize.ts | 2 +- Source/utils/nonNull.ts | 49 +- Source/utils/openUrl.ts | 8 +- Source/utils/randomUtils.ts | 17 +- Source/utils/settingUtils.ts | 98 +- Source/utils/timeout.ts | 70 +- Source/utils/vscodeUtils.ts | 180 +- Source/utils/workspacUtils.ts | 21 +- Source/utils/wrapError.ts | 26 +- Source/vscode-cosmosdb.api.d.ts | 154 +- Source/vscode-cosmosdbgraph.api.d.ts | 26 +- build/vscode-languageserver-files-stub.js | 52 +- extension.bundle.ts | 84 +- grammar/JavaScript.tmLanguage.json | 7420 ++++++++--------- grammar/Readme.md | 9 +- grammar/configuration.json | 90 +- gulpfile.ts | 39 +- main.js | 14 +- package.json | 2224 ++--- .../icons/theme-agnostic/CosmosDBAccount.svg | 57 +- .../icons/theme-agnostic/PostgresServer.svg | 28 +- tsconfig.json | 52 +- webpack.config.js | 76 +- 162 files changed, 23759 insertions(+), 17919 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eab12dcc..c7a35d26b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,403 +2,632 @@ ## 0.20.0 -This release adds the initial Azure AD authentication support for PostgreSQL flexible database servers and fixed various bugs. See [0.20.0](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.20.0+is%3Aclosed+) for all closed issues. +This release adds the initial Azure AD authentication support for PostgreSQL +flexible database servers and fixed various bugs. See +[0.20.0](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.20.0+is%3Aclosed+) +for all closed issues. ### Breaking change -- The extension is migrated to use vscode secretStorage module for storing user credentials [#2137](https://github.com/microsoft/vscode-cosmosdb/issues/2137). If you have local attachments that are broken due to this change, please re-attach them. -- The CosmosDB Graph extension has been removed from the marketplace. Attempting to open the graph explorer will open a documentation suggesting alternative tools for viewing graphs [#2086](https://github.com/microsoft/vscode-cosmosdb/issues/2086). +- The extension is migrated to use vscode secretStorage module for storing + user credentials + [#2137](https://github.com/microsoft/vscode-cosmosdb/issues/2137). If you + have local attachments that are broken due to this change, please re-attach + them. +- The CosmosDB Graph extension has been removed from the marketplace. + Attempting to open the graph explorer will open a documentation suggesting + alternative tools for viewing graphs + [#2086](https://github.com/microsoft/vscode-cosmosdb/issues/2086). ### Added -- The extension now supports connecting to PostgreSQL flexible database server as Azure AD users. Read this [wiki](https://aka.ms/postgresql-passwordless-wiki) to learn more. +- The extension now supports connecting to PostgreSQL flexible database server + as Azure AD users. Read this + [wiki](https://aka.ms/postgresql-passwordless-wiki) to learn more. ## 0.19.4 - 2023-05-17 ### Added -* Add support for the upcoming Azure Resources Focus feature + +- Add support for the upcoming Azure Resources Focus feature ## 0.19.3 - 2023-02-15 ### Added -* Forward compatibility with Azure Resources API v2 @alexweininger in [#2095](https://github.com/microsoft/vscode-cosmosdb/pull/2095) + +- Forward compatibility with Azure Resources API v2 @alexweininger in + [#2095](https://github.com/microsoft/vscode-cosmosdb/pull/2095) ### Changed -* Remove Preview label for Postgres Flexible by @tonybaloney in [#2058](https://github.com/microsoft/vscode-cosmosdb/pull/2058) -* Fix revealing attached database by @alexweininger in [#2092](https://github.com/microsoft/vscode-cosmosdb/pull/2092) + +- Remove Preview label for Postgres Flexible by @tonybaloney in + [#2058](https://github.com/microsoft/vscode-cosmosdb/pull/2058) +- Fix revealing attached database by @alexweininger in + [#2092](https://github.com/microsoft/vscode-cosmosdb/pull/2092) ### Engineering -* Remove version checker action by @alexweininger in [#2046](https://github.com/microsoft/vscode-cosmosdb/pull/2046) -* Replace public-ip with our own util to fix CVE-2022-33987 by @alexweininger in [#2048](https://github.com/microsoft/vscode-cosmosdb/pull/2048) -* Migrate to vscode-azext-dev by @alexweininger in [#2050](https://github.com/microsoft/vscode-cosmosdb/pull/2050) -* Update AppInsights key by @bwateratmsft in [#2052](https://github.com/microsoft/vscode-cosmosdb/pull/2052) -* Add post release version bumper by @alexweininger in [#2053](https://github.com/microsoft/vscode-cosmosdb/pull/2053) -* Use shared Azure Id parsing utils by @alexweininger in [#2054](https://github.com/microsoft/vscode-cosmosdb/pull/2054) -* Rename info-needed-closer by @bwateratmsft in [#2056](https://github.com/microsoft/vscode-cosmosdb/pull/2056) -* Move workflow from root to workflows folder by @alexweininger in [#2057](https://github.com/microsoft/vscode-cosmosdb/pull/2057) -* Change filter for treeItemPicker by @nturinski in [#2063](https://github.com/microsoft/vscode-cosmosdb/pull/2063) -* Finalize CodeQL settings by @bwateratmsft in [#2068](https://github.com/microsoft/vscode-cosmosdb/pull/2068) -* Fix readme badges by @bwateratmsft in [#2070](https://github.com/microsoft/vscode-cosmosdb/pull/2070) -* Skip test suite to enable CodeQL build by @nturinski in [#2081](https://github.com/microsoft/vscode-cosmosdb/pull/2081) -* Add .nvmrc file by @alexweininger in [#2085](https://github.com/microsoft/vscode-cosmosdb/pull/2085) -* Use updated AzExtTreeFileSystem by @alexweininger in [#2094](https://github.com/microsoft/vscode-cosmosdb/pull/2094) + +- Remove version checker action by @alexweininger in + [#2046](https://github.com/microsoft/vscode-cosmosdb/pull/2046) +- Replace public-ip with our own util to fix CVE-2022-33987 by @alexweininger + in [#2048](https://github.com/microsoft/vscode-cosmosdb/pull/2048) +- Migrate to vscode-azext-dev by @alexweininger in + [#2050](https://github.com/microsoft/vscode-cosmosdb/pull/2050) +- Update AppInsights key by @bwateratmsft in + [#2052](https://github.com/microsoft/vscode-cosmosdb/pull/2052) +- Add post release version bumper by @alexweininger in + [#2053](https://github.com/microsoft/vscode-cosmosdb/pull/2053) +- Use shared Azure Id parsing utils by @alexweininger in + [#2054](https://github.com/microsoft/vscode-cosmosdb/pull/2054) +- Rename info-needed-closer by @bwateratmsft in + [#2056](https://github.com/microsoft/vscode-cosmosdb/pull/2056) +- Move workflow from root to workflows folder by @alexweininger in + [#2057](https://github.com/microsoft/vscode-cosmosdb/pull/2057) +- Change filter for treeItemPicker by @nturinski in + [#2063](https://github.com/microsoft/vscode-cosmosdb/pull/2063) +- Finalize CodeQL settings by @bwateratmsft in + [#2068](https://github.com/microsoft/vscode-cosmosdb/pull/2068) +- Fix readme badges by @bwateratmsft in + [#2070](https://github.com/microsoft/vscode-cosmosdb/pull/2070) +- Skip test suite to enable CodeQL build by @nturinski in + [#2081](https://github.com/microsoft/vscode-cosmosdb/pull/2081) +- Add .nvmrc file by @alexweininger in + [#2085](https://github.com/microsoft/vscode-cosmosdb/pull/2085) +- Use updated AzExtTreeFileSystem by @alexweininger in + [#2094](https://github.com/microsoft/vscode-cosmosdb/pull/2094) ### Dependencies -* Bump extension version post release by @alexweininger in [#2045](https://github.com/microsoft/vscode-cosmosdb/pull/2045) -* Bump moment from 2.29.2 to 2.29.4 by @dependabot in [#2049](https://github.com/microsoft/vscode-cosmosdb/pull/2049) -* Bump loader-utils from 1.4.0 to 1.4.2 by @dependabot in [#2077](https://github.com/microsoft/vscode-cosmosdb/pull/2077) -* Bump yargs-parser and yargs by @dependabot in [#2078](https://github.com/microsoft/vscode-cosmosdb/pull/2078) -* Bump decode-uri-component from 0.2.0 to 0.2.2 by @dependabot in [#2083](https://github.com/microsoft/vscode-cosmosdb/pull/2083) -* Bump qs from 6.10.1 to 6.11.0 by @dependabot in [#2084](https://github.com/microsoft/vscode-cosmosdb/pull/2084) -* Bump @xmldom/xmldom from 0.7.5 to 0.7.8 by @dependabot in [#2074](https://github.com/microsoft/vscode-cosmosdb/pull/2074) -* Bump flat and mocha by @dependabot in [#2088](https://github.com/microsoft/vscode-cosmosdb/pull/2088) -* Bump json5 from 1.0.1 to 1.0.2 by @dependabot in [#2089](https://github.com/microsoft/vscode-cosmosdb/pull/2089) + +- Bump extension version post release by @alexweininger in + [#2045](https://github.com/microsoft/vscode-cosmosdb/pull/2045) +- Bump moment from 2.29.2 to 2.29.4 by @dependabot in + [#2049](https://github.com/microsoft/vscode-cosmosdb/pull/2049) +- Bump loader-utils from 1.4.0 to 1.4.2 by @dependabot in + [#2077](https://github.com/microsoft/vscode-cosmosdb/pull/2077) +- Bump yargs-parser and yargs by @dependabot in + [#2078](https://github.com/microsoft/vscode-cosmosdb/pull/2078) +- Bump decode-uri-component from 0.2.0 to 0.2.2 by @dependabot in + [#2083](https://github.com/microsoft/vscode-cosmosdb/pull/2083) +- Bump qs from 6.10.1 to 6.11.0 by @dependabot in + [#2084](https://github.com/microsoft/vscode-cosmosdb/pull/2084) +- Bump @xmldom/xmldom from 0.7.5 to 0.7.8 by @dependabot in + [#2074](https://github.com/microsoft/vscode-cosmosdb/pull/2074) +- Bump flat and mocha by @dependabot in + [#2088](https://github.com/microsoft/vscode-cosmosdb/pull/2088) +- Bump json5 from 1.0.1 to 1.0.2 by @dependabot in + [#2089](https://github.com/microsoft/vscode-cosmosdb/pull/2089) ## 0.19.2 - 2022-06-30 ### Changed -- Update @vscode/extension-telemetry to 0.6.2 [#2042](https://github.com/microsoft/vscode-cosmosdb/pull/2042) + +- Update @vscode/extension-telemetry to 0.6.2 + [#2042](https://github.com/microsoft/vscode-cosmosdb/pull/2042) ## 0.19.1 - 2022-06-01 ### Changed -- Update @vscode/extension-telemetry to 0.5.2 [#2032](https://github.com/microsoft/vscode-cosmosdb/pull/2032) + +- Update @vscode/extension-telemetry to 0.5.2 + [#2032](https://github.com/microsoft/vscode-cosmosdb/pull/2032) ## 0.19.0 - 2022-05-24 -We've made some large design changes to the Azure extensions for VS Code. [View App Centric release notes](https://aka.ms/AzCode/AppCentric) +We've made some large design changes to the Azure extensions for VS Code. +[View App Centric release notes](https://aka.ms/AzCode/AppCentric) + ### Changed -- Minimum version of VS Code is now 1.57.0 + +- Minimum version of VS Code is now 1.57.0 ## 0.18.1 - 2021-08-11 + ### [Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/32?closed=1) -- Fixed the ETIMEDOUT issue when signing into a PostgreSQL Flexible server on multiple machines + +- Fixed the ETIMEDOUT issue when signing into a PostgreSQL Flexible server on + multiple machines ## 0.18.0 - 2021-07-21 + ### Added -- Postgres Flexible Servers (Preview) includes support for Databases, Functions and Stored Procedures + +- Postgres Flexible Servers (Preview) includes support for Databases, + Functions and Stored Procedures ### Changed -- Postgres Single Server defaults to version "11" + +- Postgres Single Server defaults to version "11" ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/26?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/26?closed=1) ## 0.17.0 - 2021-06-22 + ### Added -- SKU type option is now available while creating PostgreSQL servers -- Option to select either "Provisioned throughput" or "Serverless" model while creating CosmosDB accounts + +- SKU type option is now available while creating PostgreSQL servers +- Option to select either "Provisioned throughput" or "Serverless" model while + creating CosmosDB accounts ### Changed -- Icons updated to match VS Code's theme. Install new product icon themes [here](https://marketplace.visualstudio.com/search?term=tag%3Aproduct-icon-theme&target=VSCode) + +- Icons updated to match VS Code's theme. Install new product icon themes + [here](https://marketplace.visualstudio.com/search?term=tag%3Aproduct-icon-theme&target=VSCode) ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/30?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/30?closed=1) ## 0.16.0 - 2021-02-23 + ### Added -- Now depends on the "Azure Resources" extension, which provides a "Resource Groups" and "Help and Feedback" view -- Grouped items in all context menus to improve access and readability -- "Attached Emulator..." option added to Attach Database Accounts context menu + +- Now depends on the "Azure Resources" extension, which provides a "Resource + Groups" and "Help and Feedback" view +- Grouped items in all context menus to improve access and readability +- "Attached Emulator..." option added to Attach Database Accounts context menu ### Changed -- "Report an Issue" button was removed from errors. Use the "Help and Feedback" view or command palette instead + +- "Report an Issue" button was removed from errors. Use the "Help and + Feedback" view or command palette instead ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/29?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/29?closed=1) ## 0.15.1 - 2020-12-04 + ### Added -- Newly created Azure CosmosDB - MongoDB servers default to version “3.6” + +- Newly created Azure CosmosDB - MongoDB servers default to version “3.6” ### Changed -- Minimum version of VS Code is now 1.48.0 -- Improved extension activation time (by switching to the azure-sdk-for-js) + +- Minimum version of VS Code is now 1.48.0 +- Improved extension activation time (by switching to the azure-sdk-for-js) ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/25?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/25?closed=1) ## 0.15.0 - 2020-09-15 + ### Added -- Attach PostgreSQL servers by connection string -- PostgreSQL support for integration with App Service extension + +- Attach PostgreSQL servers by connection string +- PostgreSQL support for integration with App Service extension ### Changed -- PostgreSQL server defaults to version "10" + +- PostgreSQL server defaults to version "10" ### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.15.0+is%3Aclosed) + +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.15.0+is%3Aclosed) ## 0.14.0 - 2020-07-14 + ### Added -- Use the setting "azureDatabases.batchSize" to configure the Mongo "DBQuery.shellBatchSize" attribute and the batch size when loading children in the tree view. -- Create and edit stored procedures in PostgreSQL. NOTE: only applies to PostgreSQL server versions 11 and above. + +- Use the setting "azureDatabases.batchSize" to configure the Mongo + "DBQuery.shellBatchSize" attribute and the batch size when loading children + in the tree view. +- Create and edit stored procedures in PostgreSQL. NOTE: only applies to + PostgreSQL server versions 11 and above. ### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.14.0+is%3Aclosed) + +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.14.0+is%3Aclosed) ### Changed -- Results from executing most Mongo commands open in a single read-only editor. + +- Results from executing most Mongo commands open in a single read-only + editor. ## 0.13.0 - 2020-05-28 -In this release, we're rebranding the Cosmos DB Extension to Azure Databases to expand our database support beyond just Cosmos DB. This release also marks the first new database engine: PostgreSQL with other database engines coming later this year. + +In this release, we're rebranding the Cosmos DB Extension to Azure Databases to +expand our database support beyond just Cosmos DB. This release also marks the +first new database engine: PostgreSQL with other database engines coming later +this year. + ### Added -- PostgreSQL support - - Create and view PostgreSQL servers, databases, and functions. - - Create, edit, and execute PostgreSQL queries + +- PostgreSQL support + - Create and view PostgreSQL servers, databases, and functions. + - Create, edit, and execute PostgreSQL queries ### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.13.0+is%3Aclosed) + +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.13.0+is%3Aclosed) ### Changed -- Viewing and querying Azure Cosmos DB graphs has been moved to a separate graph-specific extension, [vscode-cosmosdbgraph](https://github.com/microsoft/vscode-cosmosdbgraph) + +- Viewing and querying Azure Cosmos DB graphs has been moved to a separate + graph-specific extension, + [vscode-cosmosdbgraph](https://github.com/microsoft/vscode-cosmosdbgraph) ## 0.12.2 - 2020-03-10 + ### Fixed -- Language client is not ready yet [#1334](https://github.com/microsoft/vscode-cosmosdb/issues/1334) + +- Language client is not ready yet + [#1334](https://github.com/microsoft/vscode-cosmosdb/issues/1334) ## 0.12.1 - 2020-01-22 + ### Fixed -- When updating a Mongo document, the operation would fail with the following error: `update operation document must contain atomic operators.` [#1298](https://github.com/microsoft/vscode-cosmosdb/issues/1298) -- When importing a `.json` document into a Mongo collection, it would throw the following error: `Error: r.insertedIds is not iterable` [#1307](https://github.com/microsoft/vscode-cosmosdb/issues/1307) + +- When updating a Mongo document, the operation would fail with the following + error: `update operation document must contain atomic operators.` + [#1298](https://github.com/microsoft/vscode-cosmosdb/issues/1298) +- When importing a `.json` document into a Mongo collection, it would throw + the following error: `Error: r.insertedIds is not iterable` + [#1307](https://github.com/microsoft/vscode-cosmosdb/issues/1307) ## 0.12.0 - 2020-01-16 + ### Added -- Support for Private Endpoint Connections -- Collapse All button for Cosmos DB explorer + +- Support for Private Endpoint Connections +- Collapse All button for Cosmos DB explorer ### Fixed -- When using `find()` in MongoScrapbooks, it would not work properly with chained commands [#981](https://github.com/microsoft/vscode-cosmosdb/issues/981) -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/18?closed=1) + +- When using `find()` in MongoScrapbooks, it would not work properly with + chained commands + [#981](https://github.com/microsoft/vscode-cosmosdb/issues/981) +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/18?closed=1) ## 0.11.0 - 2019-09-03 + ### Added -- Add `mongo.shell.args` setting to allow passing arguments to mongo shell [#1104](https://github.com/Microsoft/vscode-cosmosdb/issues/1104), [#1126](https://github.com/Microsoft/vscode-cosmosdb/issues/1126) + +- Add `mongo.shell.args` setting to allow passing arguments to mongo shell + [#1104](https://github.com/Microsoft/vscode-cosmosdb/issues/1104), + [#1126](https://github.com/Microsoft/vscode-cosmosdb/issues/1126) ### Changed -- Due to a change in the Azure Cosmos DB Emulator, users must explicitly enable the Mongo DB port when starting the emulator. Updated error messages to point to debugging tips at https://aka.ms/AA5zah5. [#1137](https://github.com/microsoft/vscode-cosmosdb/issues/1137), [#1000](https://github.com/microsoft/vscode-cosmosdb/issues/1000) + +- Due to a change in the Azure Cosmos DB Emulator, users must explicitly + enable the Mongo DB port when starting the emulator. Updated error messages + to point to debugging tips at https://aka.ms/AA5zah5. + [#1137](https://github.com/microsoft/vscode-cosmosdb/issues/1137), + [#1000](https://github.com/microsoft/vscode-cosmosdb/issues/1000) ### Fixed -- Better shell error handling, add mongo.shell.args setting [#1101](https://github.com/Microsoft/vscode-cosmosdb/issues/1101), [#1092](https://github.com/Microsoft/vscode-cosmosdb/issues/1092), [#1071](https://github.com/Microsoft/vscode-cosmosdb/issues/1071), [#988](https://github.com/Microsoft/vscode-cosmosdb/issues/988), [#838](https://github.com/Microsoft/vscode-cosmosdb/issues/838), [#820](https://github.com/Microsoft/vscode-cosmosdb/issues/820) -- Increase mongo.shell.timeout default value from 5 to 30 [#1115](https://github.com/Microsoft/vscode-cosmosdb/issues/1115) -- Fix document save prompt message [#1021](https://github.com/Microsoft/vscode-cosmosdb/issues/1021) + +- Better shell error handling, add mongo.shell.args setting + [#1101](https://github.com/Microsoft/vscode-cosmosdb/issues/1101), + [#1092](https://github.com/Microsoft/vscode-cosmosdb/issues/1092), + [#1071](https://github.com/Microsoft/vscode-cosmosdb/issues/1071), + [#988](https://github.com/Microsoft/vscode-cosmosdb/issues/988), + [#838](https://github.com/Microsoft/vscode-cosmosdb/issues/838), + [#820](https://github.com/Microsoft/vscode-cosmosdb/issues/820) +- Increase mongo.shell.timeout default value from 5 to 30 + [#1115](https://github.com/Microsoft/vscode-cosmosdb/issues/1115) +- Fix document save prompt message + [#1021](https://github.com/Microsoft/vscode-cosmosdb/issues/1021) ## 0.10.2 - 2019-05-01 + ### Fixed -- Handle opening resources to use native vscode APIs -- Running the extension in older versions of VS Code -- Report an issue opening a blank webpage due to a large stack frame + +- Handle opening resources to use native vscode APIs +- Running the extension in older versions of VS Code +- Report an issue opening a blank webpage due to a large stack frame ## 0.10.1 - 2019-03-26 + ### Added -- Wizards are more informative and allow you to redo some steps + +- Wizards are more informative and allow you to redo some steps ### Fixed -- Graph views moved from using previewHtml (deprecated) to Webview API + +- Graph views moved from using previewHtml (deprecated) to Webview API ## 0.10.0 - 2019-02-13 + ### Added -* Improved startup and installation performance + +- Improved startup and installation performance ### Fixed -* Accounts created in portal are not recognized as graph/mongo by the extension [#1018](https://github.com/Microsoft/vscode-cosmosdb/issues/1018) -* Confusing error message when running 'Import Document into a Collection' with no Workspace opened [#961](https://github.com/Microsoft/vscode-cosmosdb/issues/961) -* Improve emulator connection error messages [#1016](https://github.com/Microsoft/vscode-cosmosdb/issues/1016) + +- Accounts created in portal are not recognized as graph/mongo by the + extension [#1018](https://github.com/Microsoft/vscode-cosmosdb/issues/1018) +- Confusing error message when running 'Import Document into a Collection' + with no Workspace opened + [#961](https://github.com/Microsoft/vscode-cosmosdb/issues/961) +- Improve emulator connection error messages + [#1016](https://github.com/Microsoft/vscode-cosmosdb/issues/1016) ## 0.9.1 - 2018-11-28 + ### Added -- API support for integration with [App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) -- Multiple documents, collections, or stored procedures can be viewed/edited at once (thanks [@tec-goblin](https://github.com/tec-goblin)) + +- API support for integration with + [App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) +- Multiple documents, collections, or stored procedures can be viewed/edited + at once (thanks [@tec-goblin](https://github.com/tec-goblin)) ### [Fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.9.1+label%3Abug+is%3Aclosed) -- Refresh button doesn't refresh attached accounts [#904](https://github.com/Microsoft/vscode-cosmosdb/issues/904) -- Some scrapbook parse errors were causing an error alert [#959](https://github.com/Microsoft/vscode-cosmosdb/pull/959) -- Downgrade event-stream version due to [event-stream#116](https://github.com/dominictarr/event-stream/issues/116) + +- Refresh button doesn't refresh attached accounts + [#904](https://github.com/Microsoft/vscode-cosmosdb/issues/904) +- Some scrapbook parse errors were causing an error alert + [#959](https://github.com/Microsoft/vscode-cosmosdb/pull/959) +- Downgrade event-stream version due to + [event-stream#116](https://github.com/dominictarr/event-stream/issues/116) ## 0.9.0 - 2018-11-05 + ### Added -- Mongo - - Support for [ObjectId, ISODate](https://github.com/Microsoft/vscode-cosmosdb/issues/769) and [regular expression](https://github.com/Microsoft/vscode-cosmosdb/issues/786) [(/pattern/flag)](https://github.com/Microsoft/vscode-cosmosdb/issues/667) syntax in the scrapbook - - Support for [method chaining](https://github.com/Microsoft/vscode-cosmosdb/issues/785). - - Ability to [change timeout](https://github.com/Microsoft/vscode-cosmosdb/issues/809) for commands in scrapbook -- Support [importing documents](https://github.com/Microsoft/vscode-cosmosdb/issues/404) into CosmosDB and Mongo databases. -- Support for [soveriegn clouds](https://github.com/Microsoft/vscode-cosmosdb/commit/5b573f535cdeba109d7ff037b914575e0172c6bd) -- Support creation of fixed collections and graphs [#295](https://github.com/Microsoft/vscode-cosmosdb/issues/295) and [#504](https://github.com/Microsoft/vscode-cosmosdb/issues/504) + +- Mongo + - Support for + [ObjectId, ISODate](https://github.com/Microsoft/vscode-cosmosdb/issues/769) + and + [regular expression](https://github.com/Microsoft/vscode-cosmosdb/issues/786) + [(/pattern/flag)](https://github.com/Microsoft/vscode-cosmosdb/issues/667) + syntax in the scrapbook + - Support for + [method chaining](https://github.com/Microsoft/vscode-cosmosdb/issues/785). + - Ability to + [change timeout](https://github.com/Microsoft/vscode-cosmosdb/issues/809) + for commands in scrapbook +- Support + [importing documents](https://github.com/Microsoft/vscode-cosmosdb/issues/404) + into CosmosDB and Mongo databases. +- Support for + [soveriegn clouds](https://github.com/Microsoft/vscode-cosmosdb/commit/5b573f535cdeba109d7ff037b914575e0172c6bd) +- Support creation of fixed collections and graphs + [#295](https://github.com/Microsoft/vscode-cosmosdb/issues/295) and + [#504](https://github.com/Microsoft/vscode-cosmosdb/issues/504) ### Fixed -- Collections having two documents of the same id will render properly [#588](https://github.com/Microsoft/vscode-cosmosdb/issues/588) and [#892](https://github.com/Microsoft/vscode-cosmosdb/issues/892) -- Some UI fixes [#576](https://github.com/Microsoft/vscode-cosmosdb/issues/576) and [#873](https://github.com/Microsoft/vscode-cosmosdb/issues/873) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/milestone/16?closed=1) + +- Collections having two documents of the same id will render properly + [#588](https://github.com/Microsoft/vscode-cosmosdb/issues/588) and + [#892](https://github.com/Microsoft/vscode-cosmosdb/issues/892) +- Some UI fixes + [#576](https://github.com/Microsoft/vscode-cosmosdb/issues/576) and + [#873](https://github.com/Microsoft/vscode-cosmosdb/issues/873) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/milestone/16?closed=1) ### Thank you -A big thank you to the following contributors that helped make the extension even better! -- [Nicolas Kyriazopuolos-Panagiotopoulos @tec-goblin](https://github.com/tec-goblin): - - Updates to a collection now update the corresponding tree item [PR#856](https://github.com/Microsoft/vscode-cosmosdb/pull/856) - - Uploading a document by closing it no longer tries to update the closed editor [PR#818](https://github.com/Microsoft/vscode-cosmosdb/pull/818) - - Fixing tslint issues [PR#829](https://github.com/Microsoft/vscode-cosmosdb/pull/829) - - Use consistent language for various commands [PR#828](https://github.com/Microsoft/vscode-cosmosdb/pull/828) - - Fix some typos [PR#810](https://github.com/Microsoft/vscode-cosmosdb/pull/810) and [PR#816](https://github.com/Microsoft/vscode-cosmosdb/pull/816) -- [Nguyen Long Nhat @torn4dom4n](https://github.com/torn4dom4n), for updating our tasks [PR#887](https://github.com/Microsoft/vscode-cosmosdb/pull/887) + +A big thank you to the following contributors that helped make the extension +even better! + +- [Nicolas Kyriazopuolos-Panagiotopoulos @tec-goblin](https://github.com/tec-goblin): + - Updates to a collection now update the corresponding tree item + [PR#856](https://github.com/Microsoft/vscode-cosmosdb/pull/856) + - Uploading a document by closing it no longer tries to update the closed + editor [PR#818](https://github.com/Microsoft/vscode-cosmosdb/pull/818) + - Fixing tslint issues + [PR#829](https://github.com/Microsoft/vscode-cosmosdb/pull/829) + - Use consistent language for various commands + [PR#828](https://github.com/Microsoft/vscode-cosmosdb/pull/828) + - Fix some typos + [PR#810](https://github.com/Microsoft/vscode-cosmosdb/pull/810) and + [PR#816](https://github.com/Microsoft/vscode-cosmosdb/pull/816) +- [Nguyen Long Nhat @torn4dom4n](https://github.com/torn4dom4n), for updating + our tasks [PR#887](https://github.com/Microsoft/vscode-cosmosdb/pull/887) ## 0.8.0 - 2018-07-05 + ### Added -- Improved scrapbook experience with better error handling. We now [highlight errors on the scrapbook as you type](https://github.com/Microsoft/vscode-cosmosdb/issues/471)! -- See your [stored procedures for graph accounts](https://github.com/Microsoft/vscode-cosmosdb/issues/422) too! -- [Document labels](https://github.com/Microsoft/vscode-cosmosdb/issues/381) in the tree view are now more descriptive. + +- Improved scrapbook experience with better error handling. We now + [highlight errors on the scrapbook as you type](https://github.com/Microsoft/vscode-cosmosdb/issues/471)! +- See your + [stored procedures for graph accounts](https://github.com/Microsoft/vscode-cosmosdb/issues/422) + too! +- [Document labels](https://github.com/Microsoft/vscode-cosmosdb/issues/381) + in the tree view are now more descriptive. ### Fixed -- Scrapbook: can now parse commands with [single quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467) or [no quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467). Examples from the mongo docs should now work when directly pasted. -- Fewer timeout errors on [running commands in the emulator](https://github.com/Microsoft/vscode-cosmosdb/pull/731). -- We correctly parse [collection names with dots](https://github.com/Microsoft/vscode-cosmosdb/issues/666) -- Invalid database accounts will not [prevent the tree from loading](https://github.com/Microsoft/vscode-cosmosdb/issues/628) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?page=1&q=is%3Aissue+milestone%3A0.8.0+is%3Aclosed) + +- Scrapbook: can now parse commands with + [single quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467) or + [no quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467). + Examples from the mongo docs should now work when directly pasted. +- Fewer timeout errors on + [running commands in the emulator](https://github.com/Microsoft/vscode-cosmosdb/pull/731). +- We correctly parse + [collection names with dots](https://github.com/Microsoft/vscode-cosmosdb/issues/666) +- Invalid database accounts will not + [prevent the tree from loading](https://github.com/Microsoft/vscode-cosmosdb/issues/628) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?page=1&q=is%3Aissue+milestone%3A0.8.0+is%3Aclosed) ## 0.7.2 - 2018-06-08 ### Added -- [Support DNS Seedlist Connection Format](https://github.com/Microsoft/vscode-cosmosdb/pull/670) for mongo connection strings (mongodb+srv://). Thanks [@plusn-nuri](https://github.com/plusn-nuri)! + +- [Support DNS Seedlist Connection Format](https://github.com/Microsoft/vscode-cosmosdb/pull/670) + for mongo connection strings (mongodb+srv://). Thanks + [@plusn-nuri](https://github.com/plusn-nuri)! ### Fixed -- [Support for Extended JSON in scrapbook queries](https://github.com/Microsoft/vscode-cosmosdb/issues/621) -- [Updating mongo documents without an ObjectID in the ID field ](https://github.com/Microsoft/vscode-cosmosdb/issues/534) -- [Log of fixed bugs](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.7.2+is%3Aclosed) + +- [Support for Extended JSON in scrapbook queries](https://github.com/Microsoft/vscode-cosmosdb/issues/621) +- [Updating mongo documents without an ObjectID in the ID field ](https://github.com/Microsoft/vscode-cosmosdb/issues/534) +- [Log of fixed bugs](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.7.2+is%3Aclosed) ## 0.7.1 - 2018-05-10 ### [Fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.1%22+is%3Aclosed+label%3Abug) -- Fixed error "Unexpected Experience Value" when retrieving database accounts +- Fixed error "Unexpected Experience Value" when retrieving database accounts ## 0.7.0 - 2018-05-04 ### Added -- Mongo - - CodeLens support for scrapbook - - Execute all commands in a scrapbook, allowing you to use scrapbooks as scripts - - Support for ObjectIDs, ISODate, and extended JSON data types in document views -- SQL - - View, open, edit and update Stored Procedures +- Mongo + + - CodeLens support for scrapbook + - Execute all commands in a scrapbook, allowing you to use scrapbooks as + scripts + - Support for ObjectIDs, ISODate, and extended JSON data types in document + views -- Miscellaneous - - Error messages are now modal - - Open newly created docs in editor +- SQL + + - View, open, edit and update Stored Procedures + +- Miscellaneous + - Error messages are now modal + - Open newly created docs in editor ### Changed -- Moved Azure CosmosDB Explorer to new Azure view container instead of file explorer + +- Moved Azure CosmosDB Explorer to new Azure view container instead of file + explorer ### Fixed -- [Better error messages for connection strings](https://github.com/Microsoft/vscode-cosmosdb/pull/600) -- [Don't throw errors on dropping non-existent collections](https://github.com/Microsoft/vscode-cosmosdb/pull/541) -- [Errors no longer written to output in the middle of writing a scrapbook command](https://github.com/Microsoft/vscode-cosmosdb/issues/516) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.0%22+is%3Aclosed+label%3Abug) +- [Better error messages for connection strings](https://github.com/Microsoft/vscode-cosmosdb/pull/600) +- [Don't throw errors on dropping non-existent collections](https://github.com/Microsoft/vscode-cosmosdb/pull/541) +- [Errors no longer written to output in the middle of writing a scrapbook command](https://github.com/Microsoft/vscode-cosmosdb/issues/516) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.0%22+is%3Aclosed+label%3Abug) ## 0.6.0 - 2018-04-09 ### Added -- Mongo - - mongo.shell.path setting no longer required if shell is in system path - - Allow mongo.shell.path to be specified in workspace settings as well as user settings - - No longer asking for an id for new documents - - Connected database is now persisted between sessions - - Improvements to scrapbook setup and error handling +- Mongo -- Azure subscriptions - - New "filter" button on subscription nodes - - New "Open in Portal" menu item for subscriptions + - mongo.shell.path setting no longer required if shell is in system path + - Allow mongo.shell.path to be specified in workspace settings as well as + user settings + - No longer asking for an id for new documents + - Connected database is now persisted between sessions + - Improvements to scrapbook setup and error handling -- Miscellaneous - - New "Report an Issue" button on error dialogs +- Azure subscriptions + + - New "filter" button on subscription nodes + - New "Open in Portal" menu item for subscriptions + +- Miscellaneous + - New "Report an Issue" button on error dialogs ### Fixed -- [Allow access to multi-tenant mongo server](https://github.com/Microsoft/vscode-cosmosdb/issues/473) -- [Can only run the first command in a Mongo Scrapbook on Windows](https://github.com/Microsoft/vscode-cosmosdb/issues/386) -- [Projections Not Working In Mongo Scrapbooks](https://github.com/Microsoft/vscode-cosmosdb/issues/214) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.6.0%22+is%3Aclosed+label%3Abug) +- [Allow access to multi-tenant mongo server](https://github.com/Microsoft/vscode-cosmosdb/issues/473) +- [Can only run the first command in a Mongo Scrapbook on Windows](https://github.com/Microsoft/vscode-cosmosdb/issues/386) +- [Projections Not Working In Mongo Scrapbooks](https://github.com/Microsoft/vscode-cosmosdb/issues/214) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.6.0%22+is%3Aclosed+label%3Abug) ## 0.5.1 - 2018-03-23 ### Fixed -- [Bug fixed](https://github.com/Microsoft/vscode-cosmosdb/issues/372) + +- [Bug fixed](https://github.com/Microsoft/vscode-cosmosdb/issues/372) + ## 0.5.0 - 2018-03-05 ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.5.0%22+is%3Aclosed+label%3Abug) +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.5.0%22+is%3Aclosed+label%3Abug) ### Added -- DocumentDB and Mongo - - Allow updating documents and collections re-opened from a previous VS Code session -- Mongo - - Delete databases +- DocumentDB and Mongo + - Allow updating documents and collections re-opened from a previous VS + Code session +- Mongo + - Delete databases ## 0.4.0 - 2018-01-25 + ### Added -- Attach to Cosmos DB emulator -- Run commands from the command palette + +- Attach to Cosmos DB emulator +- Run commands from the command palette ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.4.0%22+is%3Aclosed+label%3Abug) + +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.4.0%22+is%3Aclosed+label%3Abug) ## 0.3.0 - 2017-12-15 + ### Added -- Attach Cosmos DB accounts by connection string -- Graph: - - Customize the color and display text of vertices through VS Code [settings](README.md#graphSettings) - - By default display vertex IDs and labels and choose vertex color based on label - - Honor current VS Code theme + +- Attach Cosmos DB accounts by connection string +- Graph: + - Customize the color and display text of vertices through VS Code + [settings](README.md#graphSettings) + - By default display vertex IDs and labels and choose vertex color based + on label + - Honor current VS Code theme ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.3.0%22+is%3Aclosed+label%3Abug) + +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.3.0%22+is%3Aclosed+label%3Abug) ## 0.2.2 - 2017-12-04 + ### Added -- View, edit, and persist a Mongo collection -- Edit and persist the result of a Mongo command + +- View, edit, and persist a Mongo collection +- Edit and persist the result of a Mongo command ## 0.2.1 - 2017-11-16 + ### Fixed -- [Graph bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.1%22+is%3Aclosed+label%3Abug) - - Source to target arrows are backwards - - Side effects from executing a Gremlin query can occur twice - - Duplicate vertices can show up in graph viewer - - Query performance improved for large graphs + +- [Graph bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.1%22+is%3Aclosed+label%3Abug) + - Source to target arrows are backwards + - Side effects from executing a Gremlin query can occur twice + - Duplicate vertices can show up in graph viewer + - Query performance improved for large graphs ## 0.2.0 - 2017-11-10 + ### Added -- Graph: - - View/Create/Delete databases and graphs - - Click on a graph to visualize data - - Query graph using [Gremlin](https://docs.microsoft.com/azure/cosmos-db/gremlin-support) -- DocumentDB: - - View/Create/Delete databases, collections, and documents -- Mongo - - View documents in the explorer -- DocumentDB and Mongo: - - Click on a document to open in the editor - - Edit a document and persist changes to the cloud +- Graph: + - View/Create/Delete databases and graphs + - Click on a graph to visualize data + - Query graph using + [Gremlin](https://docs.microsoft.com/azure/cosmos-db/gremlin-support) +- DocumentDB: + - View/Create/Delete databases, collections, and documents +- Mongo + - View documents in the explorer +- DocumentDB and Mongo: + - Click on a document to open in the editor + - Edit a document and persist changes to the cloud ### Removed -- View Mongo documents in 'result.json' by clicking on a collection in the explorer -- Edit and persist the result of a Mongo scrapbook command + +- View Mongo documents in 'result.json' by clicking on a collection in the + explorer +- Edit and persist the result of a Mongo scrapbook command ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.0%22+is%3Aclosed+label%3Abug) + +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.0%22+is%3Aclosed+label%3Abug) ## 0.1.1 - 2017-09-19 + ### Changed -- Correctly set version to preview + +- Correctly set version to preview ## 0.1.0 - 2017-09-19 + ### Added -- Cosmos DB UI component (sash) -- Connect to local MongoDB -- Create Cosmos DB (with MongoDB adaptor) -- Connect to Cosmos DB via MongoDB adaptor -- Command to launch the `mongo` shell -- Rich MongoDB intellisense in scrapbooks + +- Cosmos DB UI component (sash) +- Connect to local MongoDB +- Create Cosmos DB (with MongoDB adaptor) +- Connect to Cosmos DB via MongoDB adaptor +- Command to launch the `mongo` shell +- Rich MongoDB intellisense in scrapbooks diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f9ba8cf65..bb1fb9ac7 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,9 +1,11 @@ # Microsoft Open Source Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). Resources: -- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) -- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) -- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with + questions or concerns diff --git a/LICENSE.md b/LICENSE.md index 4b1ad51b2..21071075c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,21 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/NOTICE.html b/NOTICE.html index 7500e9041..78b671fd0 100644 --- a/NOTICE.html +++ b/NOTICE.html @@ -1,186 +1,226 @@ - - - - NOTICES AND INFORMATION - - - -

NOTICES AND INFORMATION

-

Do Not Translate or Localize

-

- This software incorporates material from third parties. - Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, - or you may send a check or money order for US $5.00, including the product name, - the open source component name, platform, and version number, to: -

-
- Source Code Compliance Team
- Microsoft Corporation
- One Microsoft Way
- Redmond, WA 98052
- USA -
-

- Notwithstanding any other terms, you may reverse engineer this software to the extent - required to debug changes to any libraries licensed under the GNU Lesser General Public License. -

-
    -
  1. -
    - - tslib 1.14.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  2. -
  3. -
    - - tslib 2.1.0 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  4. -
  5. -
    - - tslib 2.3.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  6. -
  7. -
    - - tslib 2.4.0 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  8. -
  9. -
    - - tslib 2.6.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  10. -
  11. -
    - - tslib 2.6.2 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  12. -
  13. -
    - - bson 1.1.4 - Apache-2.0 - -

    https://github.com/mongodb/js-bson#readme

    -
    • Copyright 2009 Google Inc.
    • -
    • Copyright (c) 2014, Facebook, Inc.
    • -
    • copyright (c) 2019 Denis Pushkarev
    • -
    • Copyright (c) 2008, Fair Oaks Labs, Inc.
    • -
    • Copyright Joyent, Inc. and other Node contributors.
    -
    +
    +
    +	
    +		NOTICES AND INFORMATION
    +		
    +	
    +	
    +		

    NOTICES AND INFORMATION

    +

    Do Not Translate or Localize

    +

    + This software incorporates material from third parties. Microsoft + makes certain open source code available at + https://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including + the product name, the open source component name, platform, and + version number, to: +

    +
    + Source Code Compliance Team
    + Microsoft Corporation
    + One Microsoft Way
    + Redmond, WA 98052
    + USA +
    +

    + Notwithstanding any other terms, you may reverse engineer this + software to the extent required to debug changes to any libraries + licensed under the GNU Lesser General Public License. +

    +
      +
    1. +
      + tslib 1.14.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    2. +
    3. +
      + tslib 2.1.0 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    4. +
    5. +
      + tslib 2.3.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    6. +
    7. +
      + tslib 2.4.0 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    8. +
    9. +
      + tslib 2.6.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    10. +
    11. +
      + tslib 2.6.2 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    12. +
    13. +
      + bson 1.1.4 - Apache-2.0 +

      + https://github.com/mongodb/js-bson#readme +

      +
        +
      • Copyright 2009 Google Inc.
      • +
      • Copyright (c) 2014, Facebook, Inc.
      • +
      • copyright (c) 2019 Denis Pushkarev
      • +
      • Copyright (c) 2008, Fair Oaks Labs, Inc.
      • +
      • + Copyright Joyent, Inc. and other Node contributors. +
      • +
      +
                                                Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -382,18 +422,23 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    14. -
    15. -
      - - denque 1.4.1 - Apache-2.0 - -

      https://github.com/invertase/denque#readme

      -
      • Copyright (c) 2018 Mike Diarmid
      -
      +
      +        
      +
      +
    16. +
    17. +
      + denque 1.4.1 - Apache-2.0 +

      + https://github.com/invertase/denque#readme +

      +
        +
      • Copyright (c) 2018 Mike Diarmid
      • +
      +
               Copyright (c) 2018 Mike Diarmid (Salakar) <mike.diarmid@gmail.com>
       
       Licensed under the Apache License, Version 2.0 (the "License");
      @@ -407,18 +452,22 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    18. -
    19. -
      - - jsbi 3.2.5 - Apache-2.0 - -

      https://github.com/GoogleChromeLabs/jsbi#readme

      - -
      +
      +        
      +
      +
    20. +
    21. +
      + jsbi 3.2.5 - Apache-2.0 +

      + https://github.com/GoogleChromeLabs/jsbi#readme +

      + +
                                                Apache License
                                  Version 2.0, January 2004
                               https://www.apache.org/licenses/
      @@ -595,19 +644,24 @@ 

      NOTICES AND INFORMATION

      of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS - -
      -
      -
    22. -
    23. -
      - - mongodb 3.6.10 - Apache-2.0 - -

      https://github.com/mongodb/node-mongodb-native

      -
      • (c) 2012-present MongoDB
      • -
      • (c) 2009-2012 Christian Amor Kvalheim
      -
      +
      +        
      +
      +
    24. +
    25. +
      + mongodb 3.6.10 - Apache-2.0 +

      + https://github.com/mongodb/node-mongodb-native +

      +
        +
      • (c) 2012-present MongoDB
      • +
      • (c) 2009-2012 Christian Amor Kvalheim
      • +
      +
               Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -808,18 +862,23 @@ 

      NOTICES AND INFORMATION

      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. -
      -
      -
    26. -
    27. -
      - - mongodb-extended-json 1.11.0 - Apache-2.0 - -

      http://github.com/mongodb-js/extended-json

      -
      • Copyright 2015 MongoDB Inc.
      -
      +   limitations under the License.
      +        
      +
      +
    28. +
    29. +
      + mongodb-extended-json 1.11.0 - Apache-2.0 +

      + http://github.com/mongodb-js/extended-json +

      +
        +
      • Copyright 2015 MongoDB Inc.
      • +
      +
               Apache License
       Version 2.0, January 2004
       http://www.apache.org/licenses/
      @@ -1021,18 +1080,24 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    30. -
    31. -
      - - optional-require 1.1.8 - Apache-2.0 - -

      https://github.com/jchip/optional-require#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +
      +        
      +
      +
    32. +
    33. +
      + optional-require 1.1.8 - Apache-2.0 +

      + https://github.com/jchip/optional-require#readme +

      +
        +
      • (c) Joel Chen (https://github.com/jchip)
      • +
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1129,18 +1194,23 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and -limitations under the License. -
      -
      -
    34. -
    35. -
      - - require-at 1.0.6 - Apache-2.0 - -

      https://github.com/jchip/require-at#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +limitations under the License.
      +        
      +
      +
    36. +
    37. +
      + require-at 1.0.6 - Apache-2.0 +

      + https://github.com/jchip/require-at#readme +

      +
        +
      • (c) Joel Chen (https://github.com/jchip)
      • +
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1237,18 +1307,23 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and -limitations under the License. -
      -
      -
    38. -
    39. -
      - - domelementtype 2.3.0 - BSD-2-Clause - -

      https://github.com/fb55/domelementtype#readme

      -
      • Copyright (c) Felix Bohm
      -
      +limitations under the License.
      +        
      +
      +
    40. +
    41. +
      + domelementtype 2.3.0 - BSD-2-Clause +

      + https://github.com/fb55/domelementtype#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1260,18 +1335,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    42. -
    43. -
      - - domhandler 4.3.1 - BSD-2-Clause - -

      https://github.com/fb55/domhandler#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    44. +
    45. +
      + domhandler 4.3.1 - BSD-2-Clause +

      + https://github.com/fb55/domhandler#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1283,18 +1363,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    46. -
    47. -
      - - domutils 2.8.0 - BSD-2-Clause - -

      https://github.com/fb55/domutils#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    48. +
    49. +
      + domutils 2.8.0 - BSD-2-Clause +

      + https://github.com/fb55/domutils#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1306,18 +1391,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    50. -
    51. -
      - - dotenv 8.6.0 - BSD-2-Clause - -

      https://github.com/motdotla/dotenv#readme

      -
      • Copyright (c) 2015, Scott Motte
      -
      +
      +        
      +
      +
    52. +
    53. +
      + dotenv 8.6.0 - BSD-2-Clause +

      + https://github.com/motdotla/dotenv#readme +

      +
        +
      • Copyright (c) 2015, Scott Motte
      • +
      +
               Copyright (c) 2015, Scott Motte
       All rights reserved.
       
      @@ -1341,18 +1431,23 @@ 

      NOTICES AND INFORMATION

      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    54. -
    55. -
      - - entities 2.2.0 - BSD-2-Clause - -

      https://github.com/fb55/entities#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    56. +
    57. +
      + entities 2.2.0 - BSD-2-Clause +

      + https://github.com/fb55/entities#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1364,18 +1459,24 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    58. -
    59. -
      - - webidl-conversions 3.0.1 - BSD-2-Clause - -

      https://github.com/jsdom/webidl-conversions#readme

      -
      • Copyright (c) 2014, Domenic Denicola
      -
      +
      +        
      +
      +
    60. +
    61. +
      + webidl-conversions 3.0.1 - BSD-2-Clause +

      + https://github.com/jsdom/webidl-conversions#readme +

      +
        +
      • Copyright (c) 2014, Domenic Denicola
      • +
      +
               # The BSD 2-Clause License
       
       Copyright (c) 2014, Domenic Denicola
      @@ -1388,58 +1489,69 @@ 

      NOTICES AND INFORMATION

      2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    62. -
    63. -
      - - antlr4ts 0.4.1-alpha.0 - BSD-3-Clause - -

      https://github.com/tunnelvisionlabs/antlr4ts#readme

      -
      • Copyright 2016 The ANTLR Project.
      • -
      • Copyright (c) 2016 The ANTLR Project
      -
      -        [The "BSD license"]
      -Copyright (c) 2016 The ANTLR Project
      -All rights reserved.
      -
      -Redistribution and use in source and binary forms, with or without
      -modification, are permitted provided that the following conditions
      -are met:
      -
      - 1. Redistributions of source code must retain the above copyright
      -    notice, this list of conditions and the following disclaimer.
      - 2. Redistributions in binary form must reproduce the above copyright
      -    notice, this list of conditions and the following disclaimer in the
      -    documentation and/or other materials provided with the distribution.
      - 3. Neither the name of the copyright holder nor the names of its
      -    contributors may be used to endorse or promote products derived from
      -    this software without specific prior written permission.
      -
      -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      -
      -        
      -
      -
    64. -
    65. -
      - - moo 0.5.1 - BSD-3-Clause - -

      https://github.com/tjvr/moo#readme

      -
      • Copyright (c) 2017, Tim Radvan
      -
      +
      +        
      +
      +
    66. +
    67. +
      + antlr4ts 0.4.1-alpha.0 - BSD-3-Clause +

      + https://github.com/tunnelvisionlabs/antlr4ts#readme +

      +
        +
      • Copyright 2016 The ANTLR Project.
      • +
      • Copyright (c) 2016 The ANTLR Project
      • +
      +
      +        [The "BSD license"]
      +Copyright (c) 2016 The ANTLR Project
      +All rights reserved.
      +
      +Redistribution and use in source and binary forms, with or without
      +modification, are permitted provided that the following conditions
      +are met:
      +
      + 1. Redistributions of source code must retain the above copyright
      +    notice, this list of conditions and the following disclaimer.
      + 2. Redistributions in binary form must reproduce the above copyright
      +    notice, this list of conditions and the following disclaimer in the
      +    documentation and/or other materials provided with the distribution.
      + 3. Neither the name of the copyright holder nor the names of its
      +    contributors may be used to endorse or promote products derived from
      +    this software without specific prior written permission.
      +
      +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      +
      +        
      +
      +
    68. +
    69. +
      + moo 0.5.1 - BSD-3-Clause +

      + https://github.com/tjvr/moo#readme +

      +
        +
      • Copyright (c) 2017, Tim Radvan
      • +
      +
               BSD 3-Clause License
       
       Copyright (c) 2017, Tim Radvan (tjvr)
      @@ -1469,18 +1581,21 @@ 

      NOTICES AND INFORMATION

      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    70. -
    71. -
      - - railroad-diagrams 1.0.0 - CC0-1.0 - -

      https://github.com/tabatkins/railroad-diagrams

      - -
      +
      +        
      +
      +
    72. +
    73. +
      + railroad-diagrams 1.0.0 - CC0-1.0 +

      + https://github.com/tabatkins/railroad-diagrams +

      + +
               Creative Commons Legal Code
       
       CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
      @@ -1521,18 +1636,27 @@ 

      NOTICES AND INFORMATION

      c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. - d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. -
      -
      -
    74. -
    75. -
      - - graceful-fs 4.2.10 - ISC - -

      https://github.com/isaacs/node-graceful-fs#readme

      -
      • Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      -
      +      d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
      +        
      +
      +
    76. +
    77. +
      + graceful-fs 4.2.10 - ISC +

      + https://github.com/isaacs/node-graceful-fs#readme +

      +
        +
      • + Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben + Noordhuis, and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      @@ -1548,18 +1672,23 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    78. -
    79. -
      - - inherits 2.0.4 - ISC - -

      https://github.com/isaacs/inherits#readme

      -
      • Copyright (c) Isaac Z. Schlueter
      -
      +
      +        
      +
      +
    80. +
    81. +
      + inherits 2.0.4 - ISC +

      + https://github.com/isaacs/inherits#readme +

      +
        +
      • Copyright (c) Isaac Z. Schlueter
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter
      @@ -1576,18 +1705,26 @@ 

      NOTICES AND INFORMATION

      OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    82. -
    83. -
      - - lru-cache 6.0.0 - ISC - -

      https://github.com/isaacs/node-lru-cache#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    84. +
    85. +
      + lru-cache 6.0.0 - ISC +

      + https://github.com/isaacs/node-lru-cache#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1603,18 +1740,23 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    86. -
    87. -
      - - pg-int8 1.0.1 - ISC - -

      https://github.com/charmander/pg-int8#readme

      -
      • Copyright (c) 2017, Charmander
      -
      +
      +        
      +
      +
    88. +
    89. +
      + pg-int8 1.0.1 - ISC +

      + https://github.com/charmander/pg-int8#readme +

      +
        +
      • Copyright (c) 2017, Charmander
      • +
      +
               Copyright © 2017, Charmander <~@charmander.me>
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -1628,19 +1770,29 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    90. -
    91. -
      - - sax 1.2.4 - ISC - -

      https://github.com/isaacs/sax-js#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      • -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +
      +        
      +
      +
    92. +
    93. +
      + sax 1.2.4 - ISC +

      + https://github.com/isaacs/sax-js#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      • + Copyright Mathias Bynens + <https://mathiasbynens.be/> +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1682,20 +1834,27 @@ 

      NOTICES AND INFORMATION

      LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    94. -
    95. -
      - - semver 6.3.0 - ISC - -

      https://github.com/npm/node-semver#readme

      -
      • Copyright Isaac Z.
      • -
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    96. +
    97. +
      + semver 6.3.0 - ISC +

      + https://github.com/npm/node-semver#readme +

      +
        +
      • Copyright Isaac Z.
      • +
      • Copyright Isaac Z. Schlueter
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1711,19 +1870,26 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    98. -
    99. -
      - - semver 7.5.2 - ISC - -

      https://github.com/npm/node-semver#readme

      -
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    100. +
    101. +
      + semver 7.5.2 - ISC +

      + https://github.com/npm/node-semver#readme +

      +
        +
      • Copyright Isaac Z. Schlueter
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1739,18 +1905,27 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    102. -
    103. -
      - - universal-user-agent 6.0.0 - ISC - -

      https://github.com/gr2m/universal-user-agent#readme

      -
      • Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      -
      +
      +        
      +
      +
    104. +
    105. +
      + universal-user-agent 6.0.0 - ISC +

      + https://github.com/gr2m/universal-user-agent#readme +

      +
        +
      • + Copyright (c) 2018, Gregor Martynus + (https://github.com/gr2m) +
      • +
      +
               # [ISC License](https://spdx.org/licenses/ISC)
       
       Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      @@ -1758,18 +1933,25 @@ 

      NOTICES AND INFORMATION

      Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    106. -
    107. -
      - - yallist 4.0.0 - ISC - -

      https://github.com/isaacs/yallist#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    108. +
    109. +
      + yallist 4.0.0 - ISC +

      + https://github.com/isaacs/yallist#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1785,18 +1967,24 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    110. -
    111. -
      - - @azure/abort-controller 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    112. +
    113. +
      + @azure/abort-controller 1.0.2 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1818,18 +2006,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    114. -
    115. -
      - - @azure/arm-cosmosdb 15.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    116. +
    117. +
      + @azure/arm-cosmosdb 15.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1850,18 +2044,24 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    118. -
    119. -
      - - @azure/arm-postgresql 6.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql

      -
      • Copyright (c) Microsoft Corporation.
      -
      +SOFTWARE.
      +        
      +
      +
    120. +
    121. +
      + @azure/arm-postgresql 6.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1882,18 +2082,26 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    122. -
    123. -
      - - @azure/arm-postgresql-flexible 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible

      -
      • Copyright (c) Microsoft Corporation.
      -
      +SOFTWARE.
      +        
      +
      +
    124. +
    125. +
      + + @azure/arm-postgresql-flexible 5.0.0 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -1937,18 +2145,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    126. -
    127. -
      - - @azure/arm-resources 4.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    128. +
    129. +
      + @azure/arm-resources 4.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1970,18 +2184,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    130. -
    131. -
      - - @azure/arm-resources 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    132. +
    133. +
      + @azure/arm-resources 5.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -2002,18 +2222,25 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    134. -
    135. -
      - - @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid

      - -
      +SOFTWARE.
      +        
      +
      +
    136. +
    137. +
      + + @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - + MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid +

      + +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2057,19 +2284,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    138. -
    139. -
      - - @azure/arm-resources-subscriptions 2.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions

      -
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    140. +
    141. +
      + + @azure/arm-resources-subscriptions 2.0.1 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions +

      +
        +
      • Copyright (c) 2022 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2090,19 +2325,25 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    142. -
    143. -
      - - @azure/arm-storage 18.2.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage

      -
      • Copyright (c) 2023 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +SOFTWARE.
      +        
      +
      +
    144. +
    145. +
      + @azure/arm-storage 18.2.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage +

      +
        +
      • Copyright (c) 2023 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2023 Microsoft
      @@ -2123,20 +2364,28 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    146. -
    147. -
      - - @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +SOFTWARE.
      +        
      +
      +
    148. +
    149. +
      + + @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) 2022 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2180,19 +2429,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    150. -
    151. -
      - - @azure/core-asynciterator-polyfill 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    152. +
    153. +
      + + @azure/core-asynciterator-polyfill 1.0.2 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2214,19 +2471,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    154. -
    155. -
      - - @azure/core-auth 1.5.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    156. +
    157. +
      + @azure/core-auth 1.5.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2248,20 +2511,29 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    158. -
    159. -
      - - @azure/core-client 1.7.3 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const CollectionFormatToDelimiterMap CSV
      -
      +
      +        
      +
      +
    160. +
    161. +
      + @azure/core-client 1.7.3 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) Microsoft Corporation. const + CollectionFormatToDelimiterMap CSV +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2283,19 +2555,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    162. -
    163. -
      - - @azure/core-lro 2.5.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    164. +
    165. +
      + @azure/core-lro 2.5.4 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2317,18 +2595,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    166. -
    167. -
      - - @azure/core-paging 1.2.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    168. +
    169. +
      + @azure/core-paging 1.2.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2350,20 +2634,29 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    170. -
    171. -
      - - @azure/core-rest-pipeline 1.12.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const RedactedString REDACTED Make
      -
      +
      +        
      +
      +
    172. +
    173. +
      + @azure/core-rest-pipeline 1.12.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) Microsoft Corporation. const + RedactedString REDACTED Make +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2385,19 +2678,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    174. -
    175. -
      - - @azure/core-tracing 1.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    176. +
    177. +
      + @azure/core-tracing 1.0.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2419,19 +2718,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    178. -
    179. -
      - - @azure/core-util 1.4.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    180. +
    181. +
      + @azure/core-util 1.4.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2453,19 +2758,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    182. -
    183. -
      - - @azure/cosmos 3.15.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) 2012-2015 Karan Lyons https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js
      -
      +
      +        
      +
      +
    184. +
    185. +
      + @azure/cosmos 3.15.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • + Copyright (c) 2012-2015 Karan Lyons + https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2487,19 +2801,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    186. -
    187. -
      - - @azure/logger 1.0.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    188. +
    189. +
      + @azure/logger 1.0.4 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2521,19 +2841,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    190. -
    191. -
      - - @azure/ms-rest-azure-js 2.1.0 - MIT - -

      https://github.com/Azure/ms-rest-azure-js

      -
      • Copyright (c) 2017
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    192. +
    193. +
      + @azure/ms-rest-azure-js 2.1.0 - MIT +

      + https://github.com/Azure/ms-rest-azure-js +

      +
        +
      • Copyright (c) 2017
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               MIT License
       
       Copyright (c) 2017 MIT
      @@ -2555,20 +2880,170 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    194. -
    195. -
      - - @azure/ms-rest-js 2.7.0 - MIT - -

      https://github.com/Azure/ms-rest-js

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      -
      +
      +        
      +
      +
    196. +
    197. +
      + @azure/ms-rest-js 2.7.0 - MIT +

      + https://github.com/Azure/ms-rest-js +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) 2010-2016 Robert Kieffer and other + contributors +
      • +
      +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation. All rights reserved.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    198. +
    199. +
      + @microsoft/1ds-core-js 3.2.3 - MIT +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • copyright Microsoft 2018
      • +
      • copyright Microsoft 2019
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • copyright Microsoft 2019 Simplified
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • + copyright Microsoft 2018 import AppInsightsCore as + InternalCore +
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    200. +
    201. +
      + @microsoft/1ds-post-js 3.2.3 - MIT +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • copyright Microsoft 2018
      • +
      • copyright Microsoft 2020
      • +
      • copyright Microsoft 2018-2020
      • +
      • copyright Microsoft 2022 Simple
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • + copyright Microsoft 2018-2020 import + IExtendedAppInsightsCore, SendRequestReason, + EventSendType +
      • +
      • + copyright Microsoft 2018-2020 import + IPerfManagerProvider, IValueSanitizer, + FieldValueSanitizerType, FieldValueSanitizerFunc, + SendRequestReason, EventSendType +
      • +
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    202. +
    203. +
      + + @microsoft/applicationinsights-core-js 2.8.4 - MIT + +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      +
                   MIT License
       
           Copyright (c) Microsoft Corporation. All rights reserved.
      @@ -2590,244 +3065,172 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - -
      -
      -
    204. -
    205. -
      - - @microsoft/1ds-core-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • copyright Microsoft 2018
      • -
      • copyright Microsoft 2019
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • copyright Microsoft 2019 Simplified
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018 import AppInsightsCore as InternalCore
      -
      -        Copyright (c) Microsoft Corporation.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -        
      -
      -
    206. -
    207. -
      - - @microsoft/1ds-post-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • copyright Microsoft 2018
      • -
      • copyright Microsoft 2020
      • -
      • copyright Microsoft 2018-2020
      • -
      • copyright Microsoft 2022 Simple
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018-2020 import IExtendedAppInsightsCore, SendRequestReason, EventSendType
      • -
      • copyright Microsoft 2018-2020 import IPerfManagerProvider, IValueSanitizer, FieldValueSanitizerType, FieldValueSanitizerFunc, SendRequestReason, EventSendType
      -
      -        Copyright (c) Microsoft Corporation.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -        
      -
      -
    208. -
    209. -
      - - @microsoft/applicationinsights-core-js 2.8.4 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation. All rights reserved.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    210. -
    211. -
      - - @microsoft/applicationinsights-shims 2.0.1 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Microsoft and contributors.
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation. All rights reserved.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    212. -
    213. -
      - - @microsoft/dynamicproto-js 1.1.6 - MIT - -

      https://github.com/microsoft/DynamicProto-JS#readme

      -
      • (c) James Halliday
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2012 Maximilian Antoni
      • -
      • Copyright (c) 2013 Maximilian Antoni
      • -
      • Copyright (c) 2020 Oliver Nightingale
      • -
      • Copyright (c) 2020 Oliver Nightingale A
      • -
      • Copyright (c) 2020 Oliver Nightingale An
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • Copyright (c) 2010-2013 Christian Johansen
      • -
      • Copyright (c) 2010-2014 Christian Johansen
      • -
      • Copyright (c) 2011 Sven Fuchs, Christian Johansen
      • -
      • Copyright Joyent, Inc. and other Node contributors
      • -
      • Copyright jQuery Foundation and other contributors
      • -
      • Copyright 2013 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
      • -
      • Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright 2006 Google Inc. https://code.google.com/p/google-diff-match-patch
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    214. -
    215. -
      - - @selderee/plugin-htmlparser2 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    216. -
    217. -
      - - @tootallnate/once 1.1.2 - MIT - -

      https://github.com/TooTallNate/once#readme

      - -
      +
      +        
      +
      +
    218. +
    219. +
      + + @microsoft/applicationinsights-shims 2.0.1 - MIT + +

      + https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • Copyright (c) Microsoft and contributors.
      • +
      +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation. All rights reserved.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    220. +
    221. +
      + @microsoft/dynamicproto-js 1.1.6 - MIT +

      + https://github.com/microsoft/DynamicProto-JS#readme +

      +
        +
      • (c) James Halliday
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) 2012 Maximilian Antoni
      • +
      • Copyright (c) 2013 Maximilian Antoni
      • +
      • Copyright (c) 2020 Oliver Nightingale
      • +
      • Copyright (c) 2020 Oliver Nightingale A
      • +
      • Copyright (c) 2020 Oliver Nightingale An
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • Copyright (c) 2010-2013 Christian Johansen
      • +
      • Copyright (c) 2010-2014 Christian Johansen
      • +
      • + Copyright (c) 2011 Sven Fuchs, Christian Johansen +
      • +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      • + Copyright jQuery Foundation and other contributors +
      • +
      • + Copyright 2013 jQuery Foundation, Inc. and other + contributors +
      • +
      • + Copyright (c) 2010-2014, Christian Johansen, + christian@cjohansen.no +
      • +
      • + Copyright 2005, 2014 jQuery Foundation, Inc. and + other contributors +
      • +
      • + Copyright 2006 Google Inc. + https://code.google.com/p/google-diff-match-patch +
      • +
      +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    222. +
    223. +
      + @selderee/plugin-htmlparser2 0.6.0 - MIT +

      + https://github.com/mxxii/selderee +

      + +
      +        MIT License
      +
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    224. +
    225. +
      + @tootallnate/once 1.1.2 - MIT +

      + https://github.com/TooTallNate/once#readme +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2836,18 +3239,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    226. -
    227. -
      - - @tootallnate/once 2.0.0 - MIT - -

      https://github.com/TooTallNate/once#readme

      -
      • Copyright (c) 2020 Nathan Rajlich
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    228. +
    229. +
      + @tootallnate/once 2.0.0 - MIT +

      + https://github.com/TooTallNate/once#readme +

      +
        +
      • Copyright (c) 2020 Nathan Rajlich
      • +
      +
               MIT License
       
       Copyright (c) 2020 Nathan Rajlich
      @@ -2869,18 +3277,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    230. -
    231. -
      - - @typescript-plus/fast-memoize-decorator 0.1.0 - MIT - - - -
      +
      +        
      +
      +
    232. +
    233. +
      + + @typescript-plus/fast-memoize-decorator 0.1.0 - MIT + + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2889,19 +3297,25 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    234. -
    235. -
      - - @vscode/extension-telemetry 0.6.2 - MIT - -

      https://github.com/Microsoft/vscode-extension-telemetry#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    236. +
    237. +
      + @vscode/extension-telemetry 0.6.2 - MIT +

      + https://github.com/Microsoft/vscode-extension-telemetry#readme +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      +
               vscode-extension-telemetry
       
       The MIT License (MIT)
      @@ -2924,18 +3338,19 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    238. -
    239. -
      - - 1to2 1.0.0 - MIT - - -
      • Copyright (c) 2014 3VOT
      -
      +SOFTWARE.
      +        
      +
      +
    240. +
    241. +
      + 1to2 1.0.0 - MIT + +
        +
      • Copyright (c) 2014 3VOT
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 3VOT
      @@ -2956,19 +3371,25 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    242. -
    243. -
      - - abort-controller 3.0.0 - MIT - -

      https://github.com/mysticatea/abort-controller#readme

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2017 Toru Nagashima
      -
      +
      +        
      +
      +
    244. +
    245. +
      + abort-controller 3.0.0 - MIT +

      + https://github.com/mysticatea/abort-controller#readme +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) 2017 Toru Nagashima
      • +
      +
               MIT License
       
       Copyright (c) 2017 Toru Nagashima
      @@ -2990,18 +3411,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    246. -
    247. -
      - - agent-base 6.0.2 - MIT - -

      https://github.com/TooTallNate/node-agent-base#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    248. +
    249. +
      + agent-base 6.0.2 - MIT +

      + https://github.com/TooTallNate/node-agent-base#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3010,18 +3440,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    250. -
    251. -
      - - async 3.2.3 - MIT - -

      https://caolan.github.io/async/

      -
      • Copyright (c) 2010-2018 Caolan McMahon
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    252. +
    253. +
      + async 3.2.3 - MIT +

      + https://caolan.github.io/async/ +

      +
        +
      • Copyright (c) 2010-2018 Caolan McMahon
      • +
      +
               Copyright (c) 2010-2018 Caolan McMahon
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3041,18 +3476,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    254. -
    255. -
      - - asynckit 0.4.0 - MIT - -

      https://github.com/alexindigo/asynckit#readme

      -
      • Copyright (c) 2016 Alex Indigo
      -
      +
      +        
      +
      +
    256. +
    257. +
      + asynckit 0.4.0 - MIT +

      + https://github.com/alexindigo/asynckit#readme +

      +
        +
      • Copyright (c) 2016 Alex Indigo
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Alex Indigo
      @@ -3074,18 +3514,21 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    258. -
    259. -
      - - axios 0.21.4 - MIT - -

      https://axios-http.com/

      - -
      +
      +        
      +
      +
    260. +
    261. +
      + axios 0.21.4 - MIT +

      + https://axios-http.com/ +

      + +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3105,18 +3548,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    262. -
    263. -
      - - axios 0.26.1 - MIT - -

      https://axios-http.com/

      -
      • Copyright (c) 2014-present Matt Zabriskie
      -
      +
      +        
      +
      +
    264. +
    265. +
      + axios 0.26.1 - MIT +

      + https://axios-http.com/ +

      +
        +
      • Copyright (c) 2014-present Matt Zabriskie
      • +
      +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3136,18 +3584,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    266. -
    267. -
      - - bl 2.2.1 - MIT - -

      https://github.com/rvagg/bl

      -
      • Copyright (c) 2013-2018 bl contributors
      -
      +
      +        
      +
      +
    268. +
    269. +
      + bl 2.2.1 - MIT +

      + https://github.com/rvagg/bl +

      +
        +
      • Copyright (c) 2013-2018 bl contributors
      • +
      +
               The MIT License (MIT)
       =====================
       
      @@ -3161,18 +3614,22 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    270. -
    271. -
      - - buffer-writer 2.0.0 - MIT - -

      https://github.com/brianc/node-buffer-writer#readme

      - -
      +
      +        
      +
      +
    272. +
    273. +
      + buffer-writer 2.0.0 - MIT +

      + https://github.com/brianc/node-buffer-writer#readme +

      + +
               The MIT License (MIT)
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3192,18 +3649,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    274. -
    275. -
      - - combined-stream 1.0.8 - MIT - -

      https://github.com/felixge/node-combined-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +
      +        
      +
      +
    276. +
    277. +
      + combined-stream 1.0.8 - MIT +

      + https://github.com/felixge/node-combined-stream +

      +
        +
      • + Copyright (c) 2011 Debuggable Limited + <felix@debuggable.com> +
      • +
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3223,18 +3689,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    278. -
    279. -
      - - commander 2.20.3 - MIT - -

      https://github.com/tj/commander.js#readme

      -
      • Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      -
      +
      +        
      +
      +
    280. +
    281. +
      + commander 2.20.3 - MIT +

      + https://github.com/tj/commander.js#readme +

      +
        +
      • + Copyright (c) 2011 TJ Holowaychuk + <tj@vision-media.ca> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3257,18 +3731,25 @@ 

      NOTICES AND INFORMATION

      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    282. -
    283. -
      - - core-util-is 1.0.2 - MIT - -

      https://github.com/isaacs/core-util-is#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    284. +
    285. +
      + core-util-is 1.0.2 - MIT +

      + https://github.com/isaacs/core-util-is#readme +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Copyright Node.js contributors. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3288,18 +3769,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    286. -
    287. -
      - - dayjs 1.11.2 - MIT - -

      https://day.js.org/

      -
      • Copyright (c) 2018-present, iamkun
      -
      +
      +        
      +
      +
    288. +
    289. +
      + dayjs 1.11.2 - MIT +

      https://day.js.org/

      +
        +
      • Copyright (c) 2018-present, iamkun
      • +
      +
               MIT License
       
       Copyright (c) 2018-present, iamkun
      @@ -3321,19 +3803,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    290. -
    291. -
      - - debug 4.3.4 - MIT - -

      https://github.com/debug-js/debug#readme

      -
      • Copyright (c) 2018-2021 Josh Junon
      • -
      • Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      -
      +
      +        
      +
      +
    292. +
    293. +
      + debug 4.3.4 - MIT +

      + https://github.com/debug-js/debug#readme +

      +
        +
      • Copyright (c) 2018-2021 Josh Junon
      • +
      • + Copyright (c) 2014-2017 TJ Holowaychuk + <tj@vision-media.ca> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3354,18 +3844,26 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    294. -
    295. -
      - - deepmerge 4.2.2 - MIT - -

      https://github.com/TehShrike/deepmerge

      -
      • Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      -
      +
      +        
      +
      +
    296. +
    297. +
      + deepmerge 4.2.2 - MIT +

      + https://github.com/TehShrike/deepmerge +

      +
        +
      • + Copyright (c) 2012 James Halliday, Josh Duff, and + other contributors +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      @@ -3387,19 +3885,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    298. -
    299. -
      - - define-lazy-prop 2.0.0 - MIT - -

      https://github.com/sindresorhus/define-lazy-prop#readme

      -
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +
      +        
      +
      +
    300. +
    301. +
      + define-lazy-prop 2.0.0 - MIT +

      + https://github.com/sindresorhus/define-lazy-prop#readme +

      +
        +
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3409,18 +3916,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    302. -
    303. -
      - - delayed-stream 1.0.0 - MIT - -

      https://github.com/felixge/node-delayed-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +
      +        
      +
      +
    304. +
    305. +
      + delayed-stream 1.0.0 - MIT +

      + https://github.com/felixge/node-delayed-stream +

      +
        +
      • + Copyright (c) 2011 Debuggable Limited + <felix@debuggable.com> +
      • +
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3440,18 +3955,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    306. -
    307. -
      - - discontinuous-range 1.0.0 - MIT - -

      https://github.com/dtudury/discontinuous-range

      -
      • Copyright (c) 2014 David Tudury
      -
      +
      +        
      +
      +
    308. +
    309. +
      + discontinuous-range 1.0.0 - MIT +

      + https://github.com/dtudury/discontinuous-range +

      +
        +
      • Copyright (c) 2014 David Tudury
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 David Tudury
      @@ -3473,18 +3993,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    310. -
    311. -
      - - dom-serializer 1.4.1 - MIT - -

      https://github.com/cheeriojs/dom-renderer#readme

      -
      • Copyright (c) 2014 The cheeriojs contributors
      -
      +
      +        
      +
      +
    312. +
    313. +
      + dom-serializer 1.4.1 - MIT +

      + https://github.com/cheeriojs/dom-renderer#readme +

      +
        +
      • Copyright (c) 2014 The cheeriojs contributors
      • +
      +
               License
       
       (The MIT License)
      @@ -3496,18 +4022,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    314. -
    315. -
      - - duplexer 0.1.1 - MIT - -

      https://github.com/Raynos/duplexer

      -
      • Copyright (c) 2012 Raynos.
      -
      +
      +        
      +
      +
    316. +
    317. +
      + duplexer 0.1.1 - MIT +

      + https://github.com/Raynos/duplexer +

      +
        +
      • Copyright (c) 2012 Raynos.
      • +
      +
               Copyright (c) 2012 Raynos.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3526,19 +4057,28 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -
      -
      -
    318. -
    319. -
      - - escape-string-regexp 2.0.0 - MIT - -

      https://github.com/sindresorhus/escape-string-regexp#readme

      -
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +THE SOFTWARE.
      +        
      +
      +
    320. +
    321. +
      + escape-string-regexp 2.0.0 - MIT +

      + https://github.com/sindresorhus/escape-string-regexp#readme +

      +
        +
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3548,18 +4088,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    322. -
    323. -
      - - event-stream 4.0.1 - MIT - -

      http://github.com/dominictarr/event-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    324. +
    325. +
      + event-stream 4.0.1 - MIT +

      + http://github.com/dominictarr/event-stream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3584,19 +4129,25 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    326. -
    327. -
      - - event-target-shim 5.0.1 - MIT - -

      https://github.com/mysticatea/event-target-shim

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2015 Toru Nagashima
      -
      +
      +        
      +
      +
    328. +
    329. +
      + event-target-shim 5.0.1 - MIT +

      + https://github.com/mysticatea/event-target-shim +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) 2015 Toru Nagashima
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2015 Toru Nagashima
      @@ -3619,19 +4170,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    330. -
    331. -
      - - fast-json-stable-stringify 2.1.0 - MIT - -

      https://github.com/epoberezkin/fast-json-stable-stringify

      -
      • Copyright (c) 2013 James Halliday
      • -
      • Copyright (c) 2017 Evgeny Poberezkin
      -
      +
      +        
      +
      +
    332. +
    333. +
      + fast-json-stable-stringify 2.1.0 - MIT +

      + https://github.com/epoberezkin/fast-json-stable-stringify +

      +
        +
      • Copyright (c) 2013 James Halliday
      • +
      • Copyright (c) 2017 Evgeny Poberezkin
      • +
      +
               This software is released under the MIT license:
       
       Copyright (c) 2017 Evgeny Poberezkin
      @@ -3653,18 +4210,24 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    334. -
    335. -
      - - fast-memoize 2.5.2 - MIT - -

      https://github.com/caiogondim/fast-memoize#readme

      -
      • Copyright (c) 2016 Caio Gondim
      -
      +
      +        
      +
      +
    336. +
    337. +
      + fast-memoize 2.5.2 - MIT +

      + https://github.com/caiogondim/fast-memoize#readme +

      +
        +
      • Copyright (c) 2016 Caio Gondim
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Caio Gondim
      @@ -3686,18 +4249,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    338. -
    339. -
      - - follow-redirects 1.14.8 - MIT - -

      https://github.com/follow-redirects/follow-redirects

      -
      • Copyright 2014-present Olivier Lalonde <olalonde@gmail.com> , James Talmage <james@talmage.io> , Ruben Verborgh
      -
      +
      +        
      +
      +
    340. +
    341. +
      + follow-redirects 1.14.8 - MIT +

      + https://github.com/follow-redirects/follow-redirects +

      +
        +
      • + Copyright 2014-present Olivier Lalonde + <olalonde@gmail.com> , James Talmage + <james@talmage.io> , Ruben Verborgh +
      • +
      +
               Copyright 2014–present Olivier Lalonde <olalonde@gmail.com>, James Talmage <james@talmage.io>, Ruben Verborgh
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of
      @@ -3716,18 +4289,26 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    342. -
    343. -
      - - form-data 2.5.1 - MIT - -

      https://github.com/form-data/form-data#readme

      -
      • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
      -
      +
      +        
      +
      +
    344. +
    345. +
      + form-data 2.5.1 - MIT +

      + https://github.com/form-data/form-data#readme +

      +
        +
      • + Copyright (c) 2012 Felix Geisendorfer + (felix@debuggable.com) and contributors +
      • +
      +
               Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
       
        Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3747,18 +4328,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    346. -
    347. -
      - - form-data 4.0.0 - MIT - -

      https://github.com/form-data/form-data#readme

      -
      • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
      -
      +
      +        
      +
      +
    348. +
    349. +
      + form-data 4.0.0 - MIT +

      + https://github.com/form-data/form-data#readme +

      +
        +
      • + Copyright (c) 2012 Felix Geisendorfer + (felix@debuggable.com) and contributors +
      • +
      +
               Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
       
        Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3778,18 +4367,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    350. -
    351. -
      - - from 0.1.7 - MIT - -

      https://github.com/dominictarr/from#readme

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    352. +
    353. +
      + from 0.1.7 - MIT +

      + https://github.com/dominictarr/from#readme +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3814,20 +4408,31 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    354. -
    355. -
      - - fs-extra 8.1.0 - MIT - -

      https://github.com/jprichardson/node-fs-extra

      -
      • Copyright (c) 2011-2017 JP Richardson
      • -
      • Copyright (c) 2011-2017 JP Richardson (https://github.com/jprichardson)
      • -
      • Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
      -
      +
      +        
      +
      +
    356. +
    357. +
      + fs-extra 8.1.0 - MIT +

      + https://github.com/jprichardson/node-fs-extra +

      +
        +
      • Copyright (c) 2011-2017 JP Richardson
      • +
      • + Copyright (c) 2011-2017 JP Richardson + (https://github.com/jprichardson) +
      • +
      • + Copyright (c) 2014-2016 Jonathan Ong + me@jongleberry.com and Contributors +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2011-2017 JP Richardson
      @@ -3843,18 +4448,22 @@ 

      NOTICES AND INFORMATION

      WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    358. -
    359. -
      - - he 1.2.0 - MIT - -

      https://mths.be/he

      -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +
      +        
      +
      +
    360. +
    361. +
      + he 1.2.0 - MIT +

      https://mths.be/he

      +
        +
      • + Copyright Mathias Bynens + <https://mathiasbynens.be/> +
      • +
      +
               Copyright Mathias Bynens <https://mathiasbynens.be/>
       
       Permission is hereby granted, free of charge, to any person obtaining
      @@ -3875,18 +4484,26 @@ 

      NOTICES AND INFORMATION

      LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    362. -
    363. -
      - - htmlparser2 6.1.0 - MIT - -

      https://github.com/fb55/htmlparser2#readme

      -
      • Copyright 2010, 2011, Chris Winberry <chris@winberry.net>
      -
      +
      +        
      +
      +
    364. +
    365. +
      + htmlparser2 6.1.0 - MIT +

      + https://github.com/fb55/htmlparser2#readme +

      +
        +
      • + Copyright 2010, 2011, Chris Winberry + <chris@winberry.net> +
      • +
      +
               Copyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.
       Permission is hereby granted, free of charge, to any person obtaining a copy
       of this software and associated documentation files (the "Software"), to
      @@ -3904,19 +4521,31 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -
      -
      -
    366. -
    367. -
      - - html-to-text 8.2.0 - MIT - -

      https://github.com/html-to-text/node-html-to-text

      -
      • Portions Copyright (c) 2020 KillyMXI <killy@mxii.eu.org>
      • -
      • Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
      -
      +IN THE SOFTWARE.
      +        
      +
      +
    368. +
    369. +
      + html-to-text 8.2.0 - MIT +

      + https://github.com/html-to-text/node-html-to-text +

      +
        +
      • + Portions Copyright (c) 2020 KillyMXI + <killy@mxii.eu.org> +
      • +
      • + Portions Copyright (c) 2012-2019 werk85 + <malte@werk85.de> +
      • +
      +
               MIT License
       
       Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
      @@ -3942,18 +4571,27 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    370. -
    371. -
      - - http-proxy-agent 4.0.1 - MIT - -

      https://github.com/TooTallNate/node-http-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    372. +
    373. +
      + http-proxy-agent 4.0.1 - MIT +

      + https://github.com/TooTallNate/node-http-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3962,18 +4600,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    374. -
    375. -
      - - http-proxy-agent 5.0.0 - MIT - -

      https://github.com/TooTallNate/node-http-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    376. +
    377. +
      + http-proxy-agent 5.0.0 - MIT +

      + https://github.com/TooTallNate/node-http-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3982,18 +4629,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    378. -
    379. -
      - - https-proxy-agent 5.0.0 - MIT - -

      https://github.com/TooTallNate/node-https-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    380. +
    381. +
      + https-proxy-agent 5.0.0 - MIT +

      + https://github.com/TooTallNate/node-https-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4002,18 +4658,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    382. -
    383. -
      - - indexable-array 0.7.0 - MIT - -

      https://github.com/ozum/indexable-array

      -
      • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    384. +
    385. +
      + indexable-array 0.7.0 - MIT +

      + https://github.com/ozum/indexable-array +

      +
        +
      • + Copyright (c) 2021 Ozum Eldogan + <ozum@ozum.net> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net>
      @@ -4035,19 +4699,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    386. -
    387. -
      - - inflection 1.12.0 - MIT - -

      https://github.com/dreamerslab/node.inflection#readme

      -
      • Copyright (c) 2011
      • -
      • Copyright (c) 2011 Ben Lin <ben@dreamerslab.com>
      -
      +
      +        
      +
      +
    388. +
    389. +
      + inflection 1.12.0 - MIT +

      + https://github.com/dreamerslab/node.inflection#readme +

      +
        +
      • Copyright (c) 2011
      • +
      • + Copyright (c) 2011 Ben Lin + <ben@dreamerslab.com> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4056,18 +4729,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    390. -
    391. -
      - - isarray 1.0.0 - MIT - -

      https://github.com/juliangruber/isarray

      -
      • Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    392. +
    393. +
      + isarray 1.0.0 - MIT +

      + https://github.com/juliangruber/isarray +

      +
        +
      • + Copyright (c) 2013 Julian Gruber + <julian@juliangruber.com> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4076,18 +4757,28 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    394. -
    395. -
      - - is-docker 2.2.1 - MIT - -

      https://github.com/sindresorhus/is-docker#readme

      -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    396. +
    397. +
      + is-docker 2.2.1 - MIT +

      + https://github.com/sindresorhus/is-docker#readme +

      +
        +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> + (https://sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      @@ -4097,18 +4788,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    398. -
    399. -
      - - is-wsl 2.2.0 - MIT - -

      https://github.com/sindresorhus/is-wsl#readme

      -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +
      +        
      +
      +
    400. +
    401. +
      + is-wsl 2.2.0 - MIT +

      + https://github.com/sindresorhus/is-wsl#readme +

      +
        +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -4118,20 +4817,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    402. -
    403. -
      - - json5 2.2.3 - MIT - -

      http://json5.org/

      -
      • (c) 2019 Denis Pushkarev
      • -
      • copyright (c) 2019 Denis Pushkarev
      • -
      • Copyright (c) 2012-2018 Aseem Kishore, and others
      -
      +
      +        
      +
      +
    404. +
    405. +
      + json5 2.2.3 - MIT +

      http://json5.org/

      +
        +
      • (c) 2019 Denis Pushkarev
      • +
      • copyright (c) 2019 Denis Pushkarev
      • +
      • + Copyright (c) 2012-2018 Aseem Kishore, and others +
      • +
      +
               MIT License
       
       Copyright (c) 2012-2018 Aseem Kishore, and [others].
      @@ -4155,54 +4857,72 @@ 

      NOTICES AND INFORMATION

      SOFTWARE. [others]: https://github.com/json5/json5/contributors - -
      -
      -
    406. -
    407. -
      - - jsonc-parser 2.2.1 - MIT - -

      https://github.com/microsoft/node-jsonc-parser#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright 2018, Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      -        The MIT License (MIT)
      -
      -Copyright (c) Microsoft
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    408. -
    409. -
      - - jsonfile 4.0.0 - MIT - -

      https://github.com/jprichardson/node-jsonfile#readme

      -
      • Copyright 2012-2016, JP Richardson <jprichardson@gmail.com>
      • -
      • Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
      -
      +
      +        
      +
      +
    410. +
    411. +
      + jsonc-parser 2.2.1 - MIT +

      + https://github.com/microsoft/node-jsonc-parser#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright 2018, Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) Microsoft
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    412. +
    413. +
      + jsonfile 4.0.0 - MIT +

      + https://github.com/jprichardson/node-jsonfile#readme +

      +
        +
      • + Copyright 2012-2016, JP Richardson + <jprichardson@gmail.com> +
      • +
      • + Copyright (c) 2012-2015, JP Richardson + <jprichardson@gmail.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
      @@ -4218,19 +4938,24 @@ 

      NOTICES AND INFORMATION

      WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    414. -
    415. -
      - - jsonparse 1.3.1 - MIT - -

      https://github.com/creationix/jsonparse#readme

      -
      • Copyright (c) 2012 Tim Caswell
      • -
      • Copyright (c) 2011-2012 Tim Caswell
      -
      +
      +        
      +
      +
    416. +
    417. +
      + jsonparse 1.3.1 - MIT +

      + https://github.com/creationix/jsonparse#readme +

      +
        +
      • Copyright (c) 2012 Tim Caswell
      • +
      • Copyright (c) 2011-2012 Tim Caswell
      • +
      +
               The MIT License
       
       Copyright (c) 2012 Tim Caswell
      @@ -4255,20 +4980,31 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    418. -
    419. -
      - - lodash.get 4.4.2 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    420. +
    421. +
      + lodash.get 4.4.2 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4316,20 +5052,31 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    422. -
    423. -
      - - lodash.isfunction 3.0.9 - MIT - -

      https://lodash.com/

      -
      • Copyright JS Foundation and other contributors <https://js.foundation/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    424. +
    425. +
      + lodash.isfunction 3.0.9 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright JS Foundation and other contributors + <https://js.foundation/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright JS Foundation and other contributors <https://js.foundation/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4377,20 +5124,31 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    426. -
    427. -
      - - lodash.set 4.3.2 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    428. +
    429. +
      + lodash.set 4.3.2 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4438,20 +5196,31 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    430. -
    431. -
      - - lodash.transform 4.6.0 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +
      +        
      +
      +
    432. +
    433. +
      + lodash.transform 4.6.0 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4499,18 +5268,23 @@ 

      NOTICES AND INFORMATION

      maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
      -
      -
    434. -
    435. -
      - - map-stream 0.0.7 - MIT - -

      http://github.com/dominictarr/map-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    436. +
    437. +
      + map-stream 0.0.7 - MIT +

      + http://github.com/dominictarr/map-stream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -4535,18 +5309,23 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    438. -
    439. -
      - - memory-pager 1.5.0 - MIT - -

      https://github.com/mafintosh/memory-pager

      -
      • Copyright (c) 2017 Mathias Buus
      -
      +
      +        
      +
      +
    440. +
    441. +
      + memory-pager 1.5.0 - MIT +

      + https://github.com/mafintosh/memory-pager +

      +
        +
      • Copyright (c) 2017 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2017 Mathias Buus
      @@ -4568,19 +5347,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    442. -
    443. -
      - - mime-db 1.44.0 - MIT - -

      https://github.com/jshttp/mime-db#readme

      -
      • Copyright (c) 2014 Jonathan Ong
      • -
      • Copyright (c) 2014 Jonathan Ong me@jongleberry.com
      -
      +
      +        
      +
      +
    444. +
    445. +
      + mime-db 1.44.0 - MIT +

      + https://github.com/jshttp/mime-db#readme +

      +
        +
      • Copyright (c) 2014 Jonathan Ong
      • +
      • + Copyright (c) 2014 Jonathan Ong me@jongleberry.com +
      • +
      +
               
       The MIT License (MIT)
       
      @@ -4603,21 +5389,32 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    446. -
    447. -
      - - mime-types 2.1.27 - MIT - -

      https://github.com/jshttp/mime-types#readme

      -
      • Copyright (c) 2014 Jonathan Ong
      • -
      • Copyright (c) 2015 Douglas Christopher Wilson
      • -
      • Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
      • -
      • Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
      -
      +
      +        
      +
      +
    448. +
    449. +
      + mime-types 2.1.27 - MIT +

      + https://github.com/jshttp/mime-types#readme +

      +
        +
      • Copyright (c) 2014 Jonathan Ong
      • +
      • Copyright (c) 2015 Douglas Christopher Wilson
      • +
      • + Copyright (c) 2014 Jonathan Ong + <me@jongleberry.com> +
      • +
      • + Copyright (c) 2015 Douglas Christopher Wilson + <doug@somethingdoug.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
      @@ -4641,18 +5438,21 @@ 

      NOTICES AND INFORMATION

      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    450. -
    451. -
      - - minimist 1.2.6 - MIT - -

      https://github.com/substack/minimist

      - -
      +
      +        
      +
      +
    452. +
    453. +
      + minimist 1.2.6 - MIT +

      + https://github.com/substack/minimist +

      + +
               This software is released under the MIT license:
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of
      @@ -4671,18 +5471,25 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    454. -
    455. -
      - - moment 2.29.4 - MIT - -

      https://momentjs.com/

      -
      • Copyright (c) JS Foundation and other contributors
      -
      +
      +        
      +
      +
    456. +
    457. +
      + moment 2.29.4 - MIT +

      + https://momentjs.com/ +

      +
        +
      • + Copyright (c) JS Foundation and other contributors +
      • +
      +
               Copyright (c) JS Foundation and other contributors
       
       Permission is hereby granted, free of charge, to any person
      @@ -4705,18 +5512,23 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    458. -
    459. -
      - - ms 2.1.2 - MIT - -

      https://github.com/zeit/ms#readme

      -
      • Copyright (c) 2016 Zeit, Inc.
      -
      +
      +        
      +
      +
    460. +
    461. +
      + ms 2.1.2 - MIT +

      + https://github.com/zeit/ms#readme +

      +
        +
      • Copyright (c) 2016 Zeit, Inc.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Zeit, Inc.
      @@ -4738,18 +5550,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    462. -
    463. -
      - - nearley 2.20.1 - MIT - -

      https://github.com/hardmath123/nearley#readme

      -
      • Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
      -
      +
      +        
      +
      +
    464. +
    465. +
      + nearley 2.20.1 - MIT +

      + https://github.com/hardmath123/nearley#readme +

      +
        +
      • + Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 + Kartik Chandra, Tim Radvan +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
      @@ -4771,18 +5591,22 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    466. -
    467. -
      - - node-abort-controller 3.0.1 - MIT - -

      https://github.com/southpolesteve/node-abort-controller#readme

      - -
      +
      +        
      +
      +
    468. +
    469. +
      + node-abort-controller 3.0.1 - MIT +

      + https://github.com/southpolesteve/node-abort-controller#readme +

      + +
               MIT License
       
       Copyright (c) 2019 Steve Faulkner
      @@ -4804,18 +5628,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    470. -
    471. -
      - - node-fetch 2.6.7 - MIT - -

      https://github.com/bitinn/node-fetch

      -
      • Copyright (c) 2016 David Frank
      -
      +
      +        
      +
      +
    472. +
    473. +
      + node-fetch 2.6.7 - MIT +

      + https://github.com/bitinn/node-fetch +

      +
        +
      • Copyright (c) 2016 David Frank
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 David Frank
      @@ -4838,22 +5667,43 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    474. -
    475. -
      - - open 8.4.2 - MIT - -

      https://github.com/sindresorhus/open#readme

      -
      • Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
      • -
      • Copyright 2006, Jeremy White <jwhite@codeweavers.com>
      • -
      • Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
      • -
      • Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      -
      +
      +        
      +
      +
    476. +
    477. +
      + open 8.4.2 - MIT +

      + https://github.com/sindresorhus/open#readme +

      +
        +
      • + Copyright 2006, Kevin Krammer + <kevin.krammer@gmx.at> +
      • +
      • + Copyright 2006, Jeremy White + <jwhite@codeweavers.com> +
      • +
      • + Copyright 2009-2010, Fathi Boudra + <fabo@freedesktop.org> +
      • +
      • + Copyright 2009-2010, Rex Dieter + <rdieter@fedoraproject.org> +
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> + (https://sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      @@ -4863,18 +5713,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    478. -
    479. -
      - - packet-reader 1.0.0 - MIT - -

      https://github.com/brianc/node-packet-reader

      -
      • Copyright 2015 Brian M. Carlson
      -
      +
      +        
      +
      +
    480. +
    481. +
      + packet-reader 1.0.0 - MIT +

      + https://github.com/brianc/node-packet-reader +

      +
        +
      • Copyright 2015 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4883,71 +5738,87 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    482. -
    483. -
      - - parseley 0.7.0 - MIT - -

      https://github.com/mxxii/parseley

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    484. -
    485. -
      - - performance-now 2.1.0 - MIT - -

      https://github.com/braveg1rl/performance-now

      -
      • Copyright (c) 2013 Braveg1rl
      • -
      • Copyright (c) 2017 Braveg1rl
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    486. +
    487. +
      + parseley 0.7.0 - MIT +

      + https://github.com/mxxii/parseley +

      + +
      +        MIT License
      +
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    488. +
    489. +
      + performance-now 2.1.0 - MIT +

      + https://github.com/braveg1rl/performance-now +

      +
        +
      • Copyright (c) 2013 Braveg1rl
      • +
      • Copyright (c) 2017 Braveg1rl
      • +
      +
               Copyright (c) 2013 Braveg1rl
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
       
       The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
       
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -        
      -
      -
    490. -
    491. -
      - - pg 8.11.2 - MIT - -

      https://github.com/brianc/node-postgres

      -
      • Copyright (c) 2010 - 2021 Brian Carlson
      • -
      • Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    492. +
    493. +
      + pg 8.11.2 - MIT +

      + https://github.com/brianc/node-postgres +

      +
        +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      • + Copyright (c) 2010-2020 Brian Carlson + (brian.m.carlson@gmail.com) +
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -4969,19 +5840,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    494. -
    495. -
      - - pg-cloudflare 1.1.1 - MIT - -

      https://github.com/brianc/node-postgres#readme

      -
      • Copyright (c) 2023 Brian M. Carlson
      • -
      • Copyright (c) 2010 - 2021 Brian Carlson
      -
      +
      +        
      +
      +
    496. +
    497. +
      + pg-cloudflare 1.1.1 - MIT +

      + https://github.com/brianc/node-postgres#readme +

      +
        +
      • Copyright (c) 2023 Brian M. Carlson
      • +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -5003,19 +5879,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    498. -
    499. -
      - - pg-connection-string 2.6.2 - MIT - -

      https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string

      -
      • Copyright (c) 2014 Iced Development
      • -
      • Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
      -
      +
      +        
      +
      +
    500. +
    501. +
      + pg-connection-string 2.6.2 - MIT +

      + https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string +

      +
        +
      • Copyright (c) 2014 Iced Development
      • +
      • + Copyright (c) 2010-2014 Brian Carlson + (brian.m.carlson@gmail.com) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 Iced Development
      @@ -5036,18 +5921,23 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    502. -
    503. -
      - - pgpass 1.0.2 - MIT - -

      https://github.com/hoegaarden/pgpass#readme

      -
      • Copyright (c) 2013-2016 Hannes Horl
      -
      +SOFTWARE.
      +        
      +
      +
    504. +
    505. +
      + pgpass 1.0.2 - MIT +

      + https://github.com/hoegaarden/pgpass#readme +

      +
        +
      • Copyright (c) 2013-2016 Hannes Horl
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5056,19 +5946,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    506. -
    507. -
      - - pg-pool 3.6.1 - MIT - -

      https://github.com/brianc/node-pg-pool#readme

      -
      • Copyright (c) 2016 Brian M. Carlson
      • -
      • Copyright (c) 2017 Brian M. Carlson
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    508. +
    509. +
      + pg-pool 3.6.1 - MIT +

      + https://github.com/brianc/node-pg-pool#readme +

      +
        +
      • Copyright (c) 2016 Brian M. Carlson
      • +
      • Copyright (c) 2017 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2017 Brian M. Carlson
      @@ -5090,18 +5985,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    510. -
    511. -
      - - pg-protocol 1.6.0 - MIT - -

      https://github.com/brianc/node-postgres#readme

      -
      • Copyright (c) 2010 - 2021 Brian Carlson
      -
      +
      +        
      +
      +
    512. +
    513. +
      + pg-protocol 1.6.0 - MIT +

      + https://github.com/brianc/node-postgres#readme +

      +
        +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -5123,18 +6023,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    514. -
    515. -
      - - pg-structure 7.15.0 - MIT - -

      https://www.pg-structure.com/

      -
      • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net> (https://www.ozum.net/)
      -
      +
      +        
      +
      +
    516. +
    517. +
      + pg-structure 7.15.0 - MIT +

      + https://www.pg-structure.com/ +

      +
        +
      • + Copyright (c) 2021 Ozum Eldogan + <ozum@ozum.net> (https://www.ozum.net/) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net> (https://www.ozum.net/)
      @@ -5156,18 +6064,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    518. -
    519. -
      - - pg-types 2.2.0 - MIT - -

      https://github.com/brianc/node-pg-types

      -
      • Copyright (c) 2014 Brian M. Carlson
      -
      +
      +        
      +
      +
    520. +
    521. +
      + pg-types 2.2.0 - MIT +

      + https://github.com/brianc/node-pg-types +

      +
        +
      • Copyright (c) 2014 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5176,19 +6089,28 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    522. -
    523. -
      - - postgres-array 2.0.0 - MIT - -

      https://github.com/bendrucker/postgres-array#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    524. +
    525. +
      + postgres-array 2.0.0 - MIT +

      + https://github.com/bendrucker/postgres-array#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5210,19 +6132,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    526. -
    527. -
      - - postgres-bytea 1.0.0 - MIT - -

      https://github.com/bendrucker/postgres-bytea#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +
      +        
      +
      +
    528. +
    529. +
      + postgres-bytea 1.0.0 - MIT +

      + https://github.com/bendrucker/postgres-bytea#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5244,19 +6175,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    530. -
    531. -
      - - postgres-date 1.0.6 - MIT - -

      https://github.com/bendrucker/postgres-date#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +
      +        
      +
      +
    532. +
    533. +
      + postgres-date 1.0.6 - MIT +

      + https://github.com/bendrucker/postgres-date#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5278,19 +6218,28 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    534. -
    535. -
      - - postgres-interval 1.2.0 - MIT - -

      https://github.com/bendrucker/postgres-interval#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +
      +        
      +
      +
    536. +
    537. +
      + postgres-interval 1.2.0 - MIT +

      + https://github.com/bendrucker/postgres-interval#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5312,18 +6261,22 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    538. -
    539. -
      - - priorityqueuejs 1.0.0 - MIT - -

      https://github.com/janogonzalez/priorityqueuejs

      - -
      +
      +        
      +
      +
    540. +
    541. +
      + priorityqueuejs 1.0.0 - MIT +

      + https://github.com/janogonzalez/priorityqueuejs +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5332,18 +6285,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    542. -
    543. -
      - - process-nextick-args 2.0.1 - MIT - -

      https://github.com/calvinmetcalf/process-nextick-args

      -
      • Copyright (c) 2015 Calvin Metcalf
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    544. +
    545. +
      + process-nextick-args 2.0.1 - MIT +

      + https://github.com/calvinmetcalf/process-nextick-args +

      +
        +
      • Copyright (c) 2015 Calvin Metcalf
      • +
      +
               # Copyright (c) 2015 Calvin Metcalf
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5363,18 +6322,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** - -
      -
      -
    546. -
    547. -
      - - raf 3.4.1 - MIT - -

      https://github.com/chrisdickinson/raf#readme

      -
      • Copyright 2013 Chris Dickinson <chris@neversaw.us>
      -
      +
      +        
      +
      +
    548. +
    549. +
      + raf 3.4.1 - MIT +

      + https://github.com/chrisdickinson/raf#readme +

      +
        +
      • + Copyright 2013 Chris Dickinson + <chris@neversaw.us> +
      • +
      +
               Copyright 2013 Chris Dickinson <chris@neversaw.us>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      @@ -5382,18 +6349,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    550. -
    551. -
      - - randexp 0.4.6 - MIT - -

      http://fent.github.io/randexp.js/

      -
      • Copyright (c) 2011 by Roly Fentanes
      -
      +
      +        
      +
      +
    552. +
    553. +
      + randexp 0.4.6 - MIT +

      + http://fent.github.io/randexp.js/ +

      +
        +
      • Copyright (c) 2011 by Roly Fentanes
      • +
      +
               Copyright (C) 2011 by Roly Fentanes
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5413,18 +6385,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    554. -
    555. -
      - - readable-stream 2.3.7 - MIT - -

      https://github.com/nodejs/readable-stream#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    556. +
    557. +
      + readable-stream 2.3.7 - MIT +

      + https://github.com/nodejs/readable-stream#readme +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Node.js is licensed for use as follows:
       
       """
      @@ -5472,18 +6452,23 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - -
      -
      -
    558. -
    559. -
      - - ret 0.1.15 - MIT - -

      https://github.com/fent/ret.js#readme

      -
      • Copyright (c) 2011 by Roly Fentanes
      -
      +
      +        
      +
      +
    560. +
    561. +
      + ret 0.1.15 - MIT +

      + https://github.com/fent/ret.js#readme +

      +
        +
      • Copyright (c) 2011 by Roly Fentanes
      • +
      +
               Copyright (C) 2011 by Roly Fentanes
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5503,19 +6488,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    562. -
    563. -
      - - safe-buffer 5.1.2 - MIT - -

      https://github.com/feross/safe-buffer

      -
      • Copyright (c) Feross Aboukhadijeh
      • -
      • Copyright (c) Feross Aboukhadijeh (http://feross.org)
      -
      +
      +        
      +
      +
    564. +
    565. +
      + safe-buffer 5.1.2 - MIT +

      + https://github.com/feross/safe-buffer +

      +
        +
      • Copyright (c) Feross Aboukhadijeh
      • +
      • + Copyright (c) Feross Aboukhadijeh + (http://feross.org) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Feross Aboukhadijeh
      @@ -5537,19 +6530,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    566. -
    567. -
      - - saslprep 1.0.3 - MIT - -

      https://github.com/reklatsmasters/saslprep#readme

      -
      • (c) Dmitriy Tsvettsikh
      • -
      • Copyright (c) 2014 Dmitry Tsvettsikh
      -
      +
      +        
      +
      +
    568. +
    569. +
      + saslprep 1.0.3 - MIT +

      + https://github.com/reklatsmasters/saslprep#readme +

      +
        +
      • (c) Dmitriy Tsvettsikh
      • +
      • Copyright (c) 2014 Dmitry Tsvettsikh
      • +
      +
               Copyright (c) 2014 Dmitry Tsvettsikh
       
       Permission is hereby granted, free of charge, to any person
      @@ -5571,51 +6570,57 @@ 

      NOTICES AND INFORMATION

      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    570. -
    571. -
      - - selderee 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    572. -
    573. -
      - - semaphore 1.0.5 - MIT - -

      https://github.com/abrkn/semaphore.js

      - -
      +OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    574. +
    575. +
      + selderee 0.6.0 - MIT +

      + https://github.com/mxxii/selderee +

      + +
      +        MIT License
      +
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    576. +
    577. +
      + semaphore 1.0.5 - MIT +

      + https://github.com/abrkn/semaphore.js +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5624,18 +6629,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    578. -
    579. -
      - - sorted-array-functions 1.3.0 - MIT - -

      https://github.com/mafintosh/sorted-array-functions

      -
      • Copyright (c) 2016 Mathias Buus
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    580. +
    581. +
      + sorted-array-functions 1.3.0 - MIT +

      + https://github.com/mafintosh/sorted-array-functions +

      +
        +
      • Copyright (c) 2016 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Mathias Buus
      @@ -5657,18 +6668,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    582. -
    583. -
      - - sparse-bitfield 3.0.3 - MIT - -

      https://github.com/mafintosh/sparse-bitfield

      -
      • Copyright (c) 2016 Mathias Buus
      -
      +
      +        
      +
      +
    584. +
    585. +
      + sparse-bitfield 3.0.3 - MIT +

      + https://github.com/mafintosh/sparse-bitfield +

      +
        +
      • Copyright (c) 2016 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Mathias Buus
      @@ -5690,18 +6706,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    586. -
    587. -
      - - split 1.0.1 - MIT - -

      http://github.com/dominictarr/split

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    588. +
    589. +
      + split 1.0.1 - MIT +

      + http://github.com/dominictarr/split +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               Copyright (c) 2011 Dominic Tarr
       
       Permission is hereby granted, free of charge, 
      @@ -5723,18 +6744,23 @@ 

      NOTICES AND INFORMATION

      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    590. -
    591. -
      - - stream-combiner 0.2.2 - MIT - -

      https://github.com/dominictarr/stream-combiner

      -
      • Copyright (c) 2012 Dominic Tarr
      -
      +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    592. +
    593. +
      + stream-combiner 0.2.2 - MIT +

      + https://github.com/dominictarr/stream-combiner +

      +
        +
      • Copyright (c) 2012 Dominic Tarr
      • +
      +
               Copyright (c) 2012 'Dominic Tarr'
       
       Permission is hereby granted, free of charge, 
      @@ -5757,18 +6783,25 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    594. -
    595. -
      - - string_decoder 1.1.1 - MIT - -

      https://github.com/nodejs/string_decoder

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    596. +
    597. +
      + string_decoder 1.1.1 - MIT +

      + https://github.com/nodejs/string_decoder +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Node.js is licensed for use as follows:
       
       """
      @@ -5817,18 +6850,16 @@ 

      NOTICES AND INFORMATION

      IN THE SOFTWARE. """ - -
      -
      -
    598. -
    599. -
      - - tas-client 0.1.45 - MIT - - - -
      +
      +        
      +
      +
    600. +
    601. +
      + tas-client 0.1.45 - MIT + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5837,18 +6868,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    602. -
    603. -
      - - through 2.3.8 - MIT - -

      https://github.com/dominictarr/through

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    604. +
    605. +
      + through 2.3.8 - MIT +

      + https://github.com/dominictarr/through +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -5873,18 +6909,21 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    606. -
    607. -
      - - tr46 0.0.3 - MIT - -

      https://github.com/Sebmaster/tr46.js#readme

      - -
      +
      +        
      +
      +
    608. +
    609. +
      + tr46 0.0.3 - MIT +

      + https://github.com/Sebmaster/tr46.js#readme +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5893,18 +6932,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    610. -
    611. -
      - - tunnel 0.0.6 - MIT - -

      https://github.com/koichik/node-tunnel/

      -
      • Copyright (c) 2012 Koichi Kobayashi
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    612. +
    613. +
      + tunnel 0.0.6 - MIT +

      + https://github.com/koichik/node-tunnel/ +

      +
        +
      • Copyright (c) 2012 Koichi Kobayashi
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 Koichi Kobayashi
      @@ -5926,19 +6970,31 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    614. -
    615. -
      - - underscore 1.12.1 - MIT - -

      https://underscorejs.org/

      -
      • Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore
      -
      +
      +        
      +
      +
    616. +
    617. +
      + underscore 1.12.1 - MIT +

      + https://underscorejs.org/ +

      +
        +
      • + Copyright (c) 2009-2020 Jeremy Ashkenas, + DocumentCloud and Investigative Reporters & + Editors +
      • +
      • + (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors Underscore +
      • +
      +
               Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative
       Reporters & Editors
       
      @@ -5962,18 +7018,26 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    618. -
    619. -
      - - universalify 0.1.2 - MIT - -

      https://github.com/RyanZim/universalify#readme

      -
      • Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
      -
      +
      +        
      +
      +
    620. +
    621. +
      + universalify 0.1.2 - MIT +

      + https://github.com/RyanZim/universalify#readme +

      +
        +
      • + Copyright (c) 2017, Ryan Zimmerman + <opensrc@ryanzim.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
      @@ -5994,18 +7058,26 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    622. -
    623. -
      - - util-deprecate 1.0.2 - MIT - -

      https://github.com/TooTallNate/util-deprecate

      -
      • Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    624. +
    625. +
      + util-deprecate 1.0.2 - MIT +

      + https://github.com/TooTallNate/util-deprecate +

      +
        +
      • + Copyright (c) 2014 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
      @@ -6030,20 +7102,34 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    626. -
    627. -
      - - uuid 3.4.0 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +
      +        
      +
      +
    628. +
    629. +
      + uuid 3.4.0 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2016 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2016 Robert Kieffer and other contributors
      @@ -6065,20 +7151,34 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    630. -
    631. -
      - - uuid 8.3.2 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2020 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +
      +        
      +
      +
    632. +
    633. +
      + uuid 8.3.2 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2020 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2020 Robert Kieffer and other contributors
      @@ -6088,20 +7188,34 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    634. -
    635. -
      - - uuid 9.0.1 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2020 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +
      +        
      +
      +
    636. +
    637. +
      + uuid 9.0.1 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2020 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2020 Robert Kieffer and other contributors
      @@ -6111,146 +7225,96 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    638. -
    639. -
      - - vscode-json-languageservice 3.5.2 - MIT - -

      https://github.com/Microsoft/vscode-json-languageservice#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      -        The MIT License (MIT)
      -
      -Copyright (c) Microsoft
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    640. -
    641. -
      - - vscode-jsonrpc 5.0.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    642. -
    643. -
      - - vscode-languageclient 6.1.3 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    644. -
    645. -
      - - vscode-languageserver 6.1.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    646. -
    647. -
      - - vscode-languageserver-protocol 3.15.3 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) TypeFox and others.
      • -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    648. -
    649. -
      - - vscode-languageserver-textdocument 1.0.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    650. +
    651. +
      + vscode-json-languageservice 3.5.2 - MIT +

      + https://github.com/Microsoft/vscode-json-languageservice#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) Microsoft
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +
      +        
      +
      +
    652. +
    653. +
      + vscode-jsonrpc 5.0.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    654. +
    655. +
      + vscode-languageclient 6.1.3 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6262,41 +7326,144 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    656. -
    657. -
      - - vscode-languageserver-types 3.15.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      -        Copyright (c) Microsoft Corporation
      -
      -All rights reserved.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -
      -        
      -
      -
    658. -
    659. -
      - - vscode-nls 4.1.2 - MIT - -

      https://github.com/Microsoft/vscode-nls#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    660. +
    661. +
      + vscode-languageserver 6.1.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    662. +
    663. +
      + + vscode-languageserver-protocol 3.15.3 - MIT + +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) TypeFox and others.
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    664. +
    665. +
      + + vscode-languageserver-textdocument 1.0.1 - MIT + +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    666. +
    667. +
      + vscode-languageserver-types 3.15.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
      +        Copyright (c) Microsoft Corporation
      +
      +All rights reserved.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +        
      +
      +
    668. +
    669. +
      + vscode-nls 4.1.2 - MIT +

      + https://github.com/Microsoft/vscode-nls#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft Corporation
      @@ -6314,18 +7481,19 @@ 

      NOTICES AND INFORMATION

      OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    670. -
    671. -
      - - vscode-tas-client 0.1.47 - MIT - - -
      • Copyright (c) Microsoft Corporation
      -
      +
      +        
      +
      +
    672. +
    673. +
      + vscode-tas-client 0.1.47 - MIT + +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -6334,19 +7502,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    674. -
    675. -
      - - vscode-uri 1.0.8 - MIT - -

      https://github.com/Microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    676. +
    677. +
      + vscode-uri 1.0.8 - MIT +

      + https://github.com/Microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6355,19 +7528,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    678. -
    679. -
      - - vscode-uri 2.1.2 - MIT - -

      https://github.com/Microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    680. +
    681. +
      + vscode-uri 2.1.2 - MIT +

      + https://github.com/Microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6376,20 +7554,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    682. -
    683. -
      - - vscode-uri 3.0.7 - MIT - -

      https://github.com/microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    684. +
    685. +
      + vscode-uri 3.0.7 - MIT +

      + https://github.com/microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6398,19 +7583,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    686. -
    687. -
      - - whatwg-url 5.0.0 - MIT - -

      https://github.com/jsdom/whatwg-url#readme

      -
      • (c) extraPathPercentEncodeSet.has
      • -
      • Copyright (c) 2015-2016 Sebastian Mayr
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    688. +
    689. +
      + whatwg-url 5.0.0 - MIT +

      + https://github.com/jsdom/whatwg-url#readme +

      +
        +
      • (c) extraPathPercentEncodeSet.has
      • +
      • Copyright (c) 2015-2016 Sebastian Mayr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2015–2016 Sebastian Mayr
      @@ -6432,18 +7622,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    690. -
    691. -
      - - xml2js 0.5.0 - MIT - -

      https://github.com/Leonidas-from-XIV/node-xml2js

      -
      • Copyright 2010, 2011, 2012, 2013
      -
      +
      +        
      +
      +
    692. +
    693. +
      + xml2js 0.5.0 - MIT +

      + https://github.com/Leonidas-from-XIV/node-xml2js +

      +
        +
      • Copyright 2010, 2011, 2012, 2013
      • +
      +
               Copyright 2010, 2011, 2012, 2013. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -6463,51 +7659,61 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    694. -
    695. -
      - - xmlbuilder 11.0.1 - MIT - -

      http://github.com/oozcitak/xmlbuilder-js

      -
      • Copyright (c) 2013 Ozgur Ozcitak
      -
      -        The MIT License (MIT)
      -
      -Copyright (c) 2013 Ozgur Ozcitak
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in
      -all copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      -THE SOFTWARE.
      -
      -        
      -
      -
    696. -
    697. -
      - - xtend 4.0.2 - MIT - -

      https://github.com/Raynos/xtend

      -
      • Copyright (c) 2012-2014 Raynos
      -
      +
      +        
      +
      +
    698. +
    699. +
      + xmlbuilder 11.0.1 - MIT +

      + http://github.com/oozcitak/xmlbuilder-js +

      +
        +
      • Copyright (c) 2013 Ozgur Ozcitak
      • +
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) 2013 Ozgur Ozcitak
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in
      +all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      +THE SOFTWARE.
      +
      +        
      +
      +
    700. +
    701. +
      + xtend 4.0.2 - MIT +

      + https://github.com/Raynos/xtend +

      +
        +
      • Copyright (c) 2012-2014 Raynos
      • +
      +
               The MIT License (MIT)
       Copyright (c) 2012-2014 Raynos.
       
      @@ -6528,18 +7734,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    702. -
    703. -
      - - JSONStream 1.3.5 - MIT OR Apache-2.0 - -

      http://github.com/dominictarr/JSONStream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    704. +
    705. +
      + JSONStream 1.3.5 - MIT OR Apache-2.0 +

      + http://github.com/dominictarr/JSONStream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -6564,18 +7775,19 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    706. -
    707. -
      - - pause-stream 0.0.11 - MIT OR Apache-2.0 - - -
      • Copyright (c) 2013 Dominic Tarr
      -
      +
      +        
      +
      +
    708. +
    709. +
      + pause-stream 0.0.11 - MIT OR Apache-2.0 + +
        +
      • Copyright (c) 2013 Dominic Tarr
      • +
      +
               Dual Licensed MIT and Apache 2
       
       The MIT License
      @@ -6806,10 +8018,11 @@ 

      NOTICES AND INFORMATION

      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. -
      -
      -
    710. -
    - - \ No newline at end of file + limitations under the License. +
    +
    +
  14. +
+ + diff --git a/README.md b/README.md index 4df65aec6..7e1e0a465 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,104 @@ - -# Azure Databases for VS Code (Preview) - - - -[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) - - - -Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). - -![Azure Databases Extension](resources/readme/overview.png) - -> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). - -# Prerequisites - -- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). - -# Features - -## Azure Databases Explorer - -- Create a database server by clicking the `+` button in the title -- View database servers and open directly in the portal -- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries -- Click on a document, stored procedure, or query to open in the editor -- Edit a document and persist changes to the cloud -- Attach a Mongo server by clicking the plug icon in the title - -![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) - -## Mongo Scrapbooks -### Run Mongo Commands with Rich Intellisense - -- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string -- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) -- Click on "New Mongo Scrapbook" in the tree title bar -- Click on "Connect to a database" to indicate which database to run the commands against -- Enter your commands and/or comments, eg: `db..find()` -- IntelliSense (auto-completions) will be provided -- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor -- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` -- Save and re-use later -![Mongo Scrapbook](resources/readme/Scrapbook.gif) - -## Import into Cosmos DB - -- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! -![Import documents](resources/readme/import_documents.gif) - -## Create an Azure Databases Server - -1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer - > If you don't already have an Azure Account, click "Create a Free Azure Account" -1. Select the 'plus' button to open the "Create Resource" menu - - ![Create resource](resources/readme/createResource.png) - -1. Choose "Create Database Server..." - - ![Create Database Server](resources/readme/createDatabaseServer.png) - -## Attach to the Cosmos DB Emulator - -* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine -* Right click 'Attached Database Accounts' and select 'Attach Emulator' - -![Attach Emulator](resources/readme/attachEmulator.png) - -## Known Issues - -- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. -- Graphs are not currently supported with the emulator -- Viewing/editing tables is not currently supported -- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). - - - -# Contributing -There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): - -* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. -* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! -* **Code**: Contribute bug fixes, features or design changes: - * Clone the repository locally and open in VS Code. - * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" - * Open the terminal (press CTRL+ \`) and run `npm install`. - * To build, press F1 and type in `Tasks: Run Build Task`. - * Debug: press F5 to start debugging the extension. - -## Legal -Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. - -## Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - - - -# Telemetry -VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). - -# License -[MIT](LICENSE.md) + +# Azure Databases for VS Code (Preview) + + + +[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) + + + +Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). + +![Azure Databases Extension](resources/readme/overview.png) + +> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). + +# Prerequisites + +- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). + +# Features + +## Azure Databases Explorer + +- Create a database server by clicking the `+` button in the title +- View database servers and open directly in the portal +- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries +- Click on a document, stored procedure, or query to open in the editor +- Edit a document and persist changes to the cloud +- Attach a Mongo server by clicking the plug icon in the title + +![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) + +## Mongo Scrapbooks +### Run Mongo Commands with Rich Intellisense + +- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string +- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) +- Click on "New Mongo Scrapbook" in the tree title bar +- Click on "Connect to a database" to indicate which database to run the commands against +- Enter your commands and/or comments, eg: `db..find()` +- IntelliSense (auto-completions) will be provided +- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor +- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` +- Save and re-use later +![Mongo Scrapbook](resources/readme/Scrapbook.gif) + +## Import into Cosmos DB + +- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! +![Import documents](resources/readme/import_documents.gif) + +## Create an Azure Databases Server + +1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer + > If you don't already have an Azure Account, click "Create a Free Azure Account" +1. Select the 'plus' button to open the "Create Resource" menu + + ![Create resource](resources/readme/createResource.png) + +1. Choose "Create Database Server..." + + ![Create Database Server](resources/readme/createDatabaseServer.png) + +## Attach to the Cosmos DB Emulator + +* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine +* Right click 'Attached Database Accounts' and select 'Attach Emulator' + +![Attach Emulator](resources/readme/attachEmulator.png) + +## Known Issues + +- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. +- Graphs are not currently supported with the emulator +- Viewing/editing tables is not currently supported +- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). + + + +# Contributing +There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): + +* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. +* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! +* **Code**: Contribute bug fixes, features or design changes: + * Clone the repository locally and open in VS Code. + * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" + * Open the terminal (press CTRL+ \`) and run `npm install`. + * To build, press F1 and type in `Tasks: Run Build Task`. + * Debug: press F5 to start debugging the extension. + +## Legal +Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. + +## Code of Conduct +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + + + +# Telemetry +VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). + +# License +[MIT](LICENSE.md) diff --git a/SECURITY.md b/SECURITY.md index f7b89984f..1e9543683 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,33 +2,54 @@ ## Security -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). - -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +Microsoft takes the security of our software products and services seriously, +which includes all source code repositories managed through our GitHub +organizations, which include [Microsoft](https://github.com/Microsoft), +[Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), +[AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and +[our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned +repository that meets +[Microsoft's definition of a security vulnerability](), +please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). +Instead, please report them to the Microsoft Security Response Center (MSRC) at +[https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to +[secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your +message with our PGP key; please download it from the +[Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, +please follow up via email to ensure we received your original message. +Additional information can be found at +[microsoft.com/msrc](https://www.microsoft.com/msrc). -Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: +Please include the requested information listed below (as much as you can +provide) to help us better understand the nature and scope of the possible +issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, + etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. +If you are reporting for a bug bounty, more complete reports can contribute to a +higher bounty award. Please visit our +[Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more +details about our active programs. ## Preferred Languages @@ -36,6 +57,7 @@ We prefer all communications to be in English. ## Policy -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). +Microsoft follows the principle of +[Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - \ No newline at end of file + diff --git a/SUPPORT.md b/SUPPORT.md index 06703d2d0..bf4fade18 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,7 +2,8 @@ ## How to file issues and get help -This project uses GitHub Issues to track bugs and feature requests. Please see https://aka.ms/azCodeIssueReporting for our issue reporting guidelines. +This project uses GitHub Issues to track bugs and feature requests. Please see +https://aka.ms/azCodeIssueReporting for our issue reporting guidelines. ## Microsoft Support Policy diff --git a/Source/AzureDBExperiences.ts b/Source/AzureDBExperiences.ts index be9765dc6..97d2221cc 100644 --- a/Source/AzureDBExperiences.ts +++ b/Source/AzureDBExperiences.ts @@ -3,116 +3,202 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { nonNullProp } from './utils/nonNull'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; +import { nonNullProp } from "./utils/nonNull"; export enum API { - MongoDB = 'MongoDB', - Graph = 'Graph', - Table = 'Table', - Core = 'Core', - PostgresSingle = 'PostgresSingle', - PostgresFlexible = 'PostgresFlexible' + MongoDB = "MongoDB", + Graph = "Graph", + Table = "Table", + Core = "Core", + PostgresSingle = "PostgresSingle", + PostgresFlexible = "PostgresFlexible", } export enum DBAccountKind { - MongoDB = 'MongoDB', - GlobalDocumentDB = 'GlobalDocumentDB' + MongoDB = "MongoDB", + GlobalDocumentDB = "GlobalDocumentDB", } -export type CapabilityName = 'EnableGremlin' | 'EnableTable'; +export type CapabilityName = "EnableGremlin" | "EnableTable"; export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; - } - return info; + let info = experiencesMap.get(api); + if (!info) { + info = { + api: api, + shortName: api, + longName: api, + kind: DBAccountKind.GlobalDocumentDB, + tag: api, + }; + } + return info; } -export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { - - const experience: Experience | undefined = tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); - const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); - return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); - +export function getExperienceLabel( + databaseAccount: DatabaseAccountGetResults +): string { + const experience: Experience | undefined = + tryGetExperience(databaseAccount); + if (experience) { + return experience.shortName; + } + // Must be some new kind of resource that we aren't aware of. Try to get a decent label + const defaultExperience: string = ( + (databaseAccount && + databaseAccount.tags && + databaseAccount.tags.defaultExperience) + ); + const firstCapability = + databaseAccount.capabilities && databaseAccount.capabilities[0]; + const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ""); + return ( + defaultExperience || + firstCapabilityName || + nonNullProp(databaseAccount, "kind") + ); } -export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { - return GremlinExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; +export function tryGetExperience( + resource: DatabaseAccountGetResults +): Experience | undefined { + // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type + if (resource.kind === DBAccountKind.MongoDB) { + return MongoExperience; + } else if ( + resource.capabilities?.find((cap) => cap.name === "EnableGremlin") + ) { + return GremlinExperience; + } else if ( + resource.capabilities?.find((cap) => cap.name === "EnableTable") + ) { + return TableExperience; + } else if (resource.capabilities?.length === 0) { + return CoreExperience; + } + + return undefined; } export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; + /** + * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) + */ + api: API; - longName: string; - shortName: string; - description?: string; + longName: string; + shortName: string; + description?: string; - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; + // These properties are what the portal actually looks at to determine the difference between APIs + kind?: DBAccountKind; + capability?: CapabilityName; - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; + // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) + tag?: string; } -export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } +export function getExperienceQuickPicks( + attached?: boolean +): IAzureQuickPickItem[] { + if (attached) { + return experiencesArray.map((exp) => + getExperienceQuickPickForAttached(exp.api) + ); + } else { + return experiencesArray.map((exp) => getExperienceQuickPick(exp.api)); + } } -export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } +export function getCosmosExperienceQuickPicks( + attached?: boolean +): IAzureQuickPickItem[] { + if (attached) { + return cosmosExperiencesArray.map((exp) => + getExperienceQuickPickForAttached(exp.api) + ); + } else { + return cosmosExperiencesArray.map((exp) => + getExperienceQuickPick(exp.api) + ); + } } -export function getExperienceQuickPick(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; +export function getExperienceQuickPick( + api: API +): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.longName, description: exp.description, data: exp }; } -export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; +export function getExperienceQuickPickForAttached( + api: API +): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.shortName, description: exp.description, data: exp }; } // Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" // Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; -export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; -export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; -export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; -const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; -const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; - -const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; -const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; -const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); +export const CoreExperience: Experience = { + api: API.Core, + longName: "Core", + description: "(SQL)", + shortName: "SQL", + kind: DBAccountKind.GlobalDocumentDB, + tag: "Core (SQL)", +} as const; +export const MongoExperience: Experience = { + api: API.MongoDB, + longName: "Azure Cosmos DB for MongoDB API", + shortName: "MongoDB", + kind: DBAccountKind.MongoDB, + tag: "Azure Cosmos DB for MongoDB API", +} as const; +export const TableExperience: Experience = { + api: API.Table, + longName: "Azure Table", + shortName: "Table", + kind: DBAccountKind.GlobalDocumentDB, + capability: "EnableTable", + tag: "Azure Table", +} as const; +export const GremlinExperience: Experience = { + api: API.Graph, + longName: "Gremlin", + description: "(graph)", + shortName: "Gremlin", + kind: DBAccountKind.GlobalDocumentDB, + capability: "EnableGremlin", + tag: "Gremlin (graph)", +} as const; +const PostgresSingleExperience: Experience = { + api: API.PostgresSingle, + longName: "PostgreSQL Single Server", + shortName: "PostgreSQLSingle", +}; +const PostgresFlexibleExperience: Experience = { + api: API.PostgresFlexible, + longName: "PostgreSQL Flexible Server", + shortName: "PostgreSQLFlexible", +}; + +const cosmosExperiencesArray: Experience[] = [ + CoreExperience, + MongoExperience, + TableExperience, + GremlinExperience, +]; +const experiencesArray: Experience[] = [ + ...cosmosExperiencesArray, + PostgresSingleExperience, + PostgresFlexibleExperience, +]; +const experiencesMap = new Map( + experiencesArray.map((info: Experience): [API, Experience] => [ + info.api, + info, + ]) +); diff --git a/Source/DatabasesFileSystem.ts b/Source/DatabasesFileSystem.ts index 93c2b4938..da2073ac0 100644 --- a/Source/DatabasesFileSystem.ts +++ b/Source/DatabasesFileSystem.ts @@ -3,7 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import { + AzExtTreeFileSystem, + AzExtTreeItem, + DialogResponses, + IActionContext, + UserCancelledError, +} from "@microsoft/vscode-azext-utils"; import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; import { FileChangeType } from "vscode-languageclient"; import { ext } from "./extensionVariables"; @@ -12,66 +18,103 @@ import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; import { getNodeEditorLabel } from "./utils/vscodeUtils"; export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; + id: string; + filePath: string; + cTime: number; + mTime: number; + getFileContent(context: IActionContext): Promise; + writeFileContent(context: IActionContext, data: string): Promise; } export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = 'azureDatabases'; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; + public static scheme: string = "azureDatabases"; + public scheme: string = DatabasesFileSystem.scheme; + private _showSaveConfirmation: boolean = true; - public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { - const size: number = Buffer.byteLength(await node.getFileContent(context)); - return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; - } + public async statImpl( + context: IActionContext, + node: IEditableTreeItem + ): Promise { + const size: number = Buffer.byteLength( + await node.getFileContent(context) + ); + return { + type: FileType.File, + ctime: node.cTime, + mtime: node.mTime, + size, + }; + } - public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { - return Buffer.from(await node.getFileContent(context)); - } + public async readFileImpl( + context: IActionContext, + node: IEditableTreeItem + ): Promise { + return Buffer.from(await node.getFileContent(context)); + } - public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { - const showSavePromptKey: string = 'showSavePrompt'; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = 'cosmosDB'; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { - const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); - const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError('dontUpload'); - } - } + public async writeFileImpl( + context: IActionContext, + node: IEditableTreeItem, + content: Uint8Array, + _originalUri: Uri + ): Promise { + const showSavePromptKey: string = "showSavePrompt"; + // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" + const prefix: string = "cosmosDB"; + const nodeEditorLabel: string = getNodeEditorLabel(node); + if ( + this._showSaveConfirmation && + getWorkspaceSetting(showSavePromptKey, undefined, prefix) + ) { + const message: string = localize( + "saveConfirmation", + 'Saving "{0}" will update the entity "{1}" to the cloud.', + node.filePath, + nodeEditorLabel + ); + const result: MessageItem | undefined = + await context.ui.showWarningMessage( + message, + { stepName: "writeFile" }, + DialogResponses.upload, + DialogResponses.alwaysUpload, + DialogResponses.dontUpload + ); + if (result === DialogResponses.alwaysUpload) { + await updateGlobalSetting(showSavePromptKey, false, prefix); + } else if (result === DialogResponses.dontUpload) { + throw new UserCancelledError("dontUpload"); + } + } - await node.writeFileContent(context, content.toString()); - await node.refresh(context); + await node.writeFileContent(context, content.toString()); + await node.refresh(context); - const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); - ext.outputChannel.appendLog(updatedMessage); - } + const updatedMessage: string = localize( + "updatedEntity", + 'Updated entity "{0}".', + nodeEditorLabel + ); + ext.outputChannel.appendLog(updatedMessage); + } - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } + public getFilePath(node: IEditableTreeItem): string { + return node.filePath; + } - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } + public async updateWithoutPrompt(uri: Uri): Promise { + const textDoc = await workspace.openTextDocument(uri); + this._showSaveConfirmation = false; + try { + await textDoc.save(); + } finally { + this._showSaveConfirmation = true; + } + } - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } + public fireChangedEvent(node: IEditableTreeItem): void { + node.mTime = Date.now(); + this.fireSoon({ type: FileChangeType.Changed, item: node }); + } } diff --git a/Source/ParsedConnectionString.ts b/Source/ParsedConnectionString.ts index 99654ef5a..1619d6390 100644 --- a/Source/ParsedConnectionString.ts +++ b/Source/ParsedConnectionString.ts @@ -4,25 +4,27 @@ *--------------------------------------------------------------------------------------------*/ export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; + public abstract readonly hostName: string; + public abstract readonly port: string; - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; + /** + * databaseName may be undefined if this is an account-level connection string + */ + public readonly databaseName: string | undefined; + public readonly connectionString: string; - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } + constructor(connectionString: string, databaseName: string | undefined) { + this.connectionString = connectionString; + this.databaseName = databaseName; + } - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } + public get accountId(): string { + return `${this.hostName}:${this.port}`; + } - public get fullId(): string { - return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; - } + public get fullId(): string { + return `${this.accountId}${ + this.databaseName ? "/" + this.databaseName : "" + }`; + } } diff --git a/Source/azureAccountUtils.ts b/Source/azureAccountUtils.ts index 7f37da4cd..fbd474ae3 100644 --- a/Source/azureAccountUtils.ts +++ b/Source/azureAccountUtils.ts @@ -9,23 +9,32 @@ import { getApiExport } from "./getExtensionApi"; const azureAccountExtensionId = "ms-vscode.azure-account"; type AzureSession = { - userId: string; + userId: string; }; /** * @returns The user session of the signed-in azure account. */ -export async function getAzureAdUserSession(): Promise { - const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; +export async function getAzureAdUserSession(): Promise< + AzureSession | undefined +> { + const azureAccountExport = (await getApiExport( + azureAccountExtensionId + )) as { sessions?: AzureSession[] }; + return azureAccountExport.sessions?.[0]; } /** * Gets a function that can request an access token for a specified scope for the signed-in azure account. */ -export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { - return async () => { - const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; - return getTokenResult?.token ?? ""; - }; +export function getTokenFunction( + credentials: AzExtServiceClientCredentials, + scope: string +): () => Promise { + return async () => { + const getTokenResult = (await credentials.getToken(scope)) as + | { token: string } + | undefined; + return getTokenResult?.token ?? ""; + }; } diff --git a/Source/commands/api/DatabaseAccountTreeItemInternal.ts b/Source/commands/api/DatabaseAccountTreeItemInternal.ts index 89a8c1164..6a5cebe8a 100644 --- a/Source/commands/api/DatabaseAccountTreeItemInternal.ts +++ b/Source/commands/api/DatabaseAccountTreeItemInternal.ts @@ -3,104 +3,146 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { API } from '../../AzureDBExperiences'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { API } from "../../AzureDBExperiences"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { ParsedPostgresConnectionString } from "../../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { nonNullProp } from "../../utils/nonNull"; +import { DatabaseAccountTreeItem } from "../../vscode-cosmosdb.api"; -export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { - protected _parsedCS: ParsedConnectionString; - private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; +export class DatabaseAccountTreeItemInternal + implements DatabaseAccountTreeItem +{ + protected _parsedCS: ParsedConnectionString; + private _accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + | undefined; - constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } + constructor( + parsedCS: ParsedConnectionString, + accountNode?: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + ) { + this._parsedCS = parsedCS; + this._accountNode = accountNode; + } - public get connectionString(): string { - return this._parsedCS.connectionString; - } + public get connectionString(): string { + return this._parsedCS.connectionString; + } - public get hostName(): string { - return this._parsedCS.hostName; - } + public get hostName(): string { + return this._parsedCS.hostName; + } - public get port(): string { - return this._parsedCS.port; - } + public get port(): string { + return this._parsedCS.port; + } - public get azureData(): { accountName: string, accountId: string } | undefined { - if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), - accountId: this._accountNode.fullId - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId - }; - } - } - return undefined; - } + public get azureData(): + | { accountName: string; accountId: string } + | undefined { + if ( + this._accountNode instanceof MongoAccountTreeItem || + this._accountNode instanceof DocDBAccountTreeItemBase + ) { + if (this._accountNode?.databaseAccount) { + return { + accountName: nonNullProp( + this._accountNode.databaseAccount, + "name" + ), + accountId: this._accountNode.fullId, + }; + } + } else if (this._accountNode instanceof PostgresServerTreeItem) { + if (this._accountNode.azureName) { + return { + accountName: this._accountNode.azureName, + accountId: this._accountNode.fullId, + }; + } + } + return undefined; + } - public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey - }; - } else { - return undefined; - } - } + public get docDBData(): + | { masterKey: string; documentEndpoint: string } + | undefined { + if (this._accountNode instanceof DocDBAccountTreeItemBase) { + return { + documentEndpoint: this._accountNode.root.endpoint, + masterKey: this._accountNode.root.masterKey, + }; + } else { + return undefined; + } + } - public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password - }; - } else { - return undefined; - } - } + public get postgresData(): + | { username: string | undefined; password: string | undefined } + | undefined { + if (this._parsedCS instanceof ParsedPostgresConnectionString) { + const connectionString = this._parsedCS; + return { + username: connectionString.username, + password: connectionString.password, + }; + } else { + return undefined; + } + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); - }); - } + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling( + "api.dbAccount.reveal", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + await ext.rgApi.appResourceTreeView.reveal( + await this.getAccountNode(context) + ); + } + ); + } - protected async getAccountNode(context: IActionContext): Promise { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { + protected async getAccountNode( + context: IActionContext + ): Promise< + MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem + > { + // If this._accountNode is undefined, attach a new node based on connection string + if (!this._accountNode) { + let apiType: API; + if (this._parsedCS instanceof ParsedMongoConnectionString) { + apiType = API.MongoDB; + } else if ( + this._parsedCS instanceof ParsedPostgresConnectionString + ) { + apiType = API.PostgresSingle; + } else { + apiType = API.Core; + } + this._accountNode = + await ext.attachedAccountsNode.attachConnectionString( + context, + this.connectionString, + apiType + ); + } - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); - } - - return this._accountNode; - } + return this._accountNode; + } } diff --git a/Source/commands/api/DatabaseTreeItemInternal.ts b/Source/commands/api/DatabaseTreeItemInternal.ts index 9d6b0d140..8fa8389b2 100644 --- a/Source/commands/api/DatabaseTreeItemInternal.ts +++ b/Source/commands/api/DatabaseTreeItemInternal.ts @@ -3,40 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { DatabaseTreeItem } from "../../vscode-cosmosdb.api"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; +export class DatabaseTreeItemInternal + extends DatabaseAccountTreeItemInternal + implements DatabaseTreeItem +{ + public databaseName: string; + private _dbNode: AzExtTreeItem | undefined; - constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } + constructor( + parsedCS: ParsedConnectionString, + databaseName: string, + accountNode?: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem, + dbNode?: + | MongoDatabaseTreeItem + | DocDBDatabaseTreeItemBase + | PostgresDatabaseTreeItem + ) { + super(parsedCS, accountNode); + this.databaseName = databaseName; + this._dbNode = dbNode; + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling( + "api.db.reveal", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); - } + const accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem = + await this.getAccountNode(context); + if (!this._dbNode) { + const databaseId = `${accountNode.fullId}/${this.databaseName}`; + this._dbNode = + await ext.rgApi.workspaceResourceTree.findTreeItem( + databaseId, + context + ); + } - await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); - }); - } + await ext.rgApi.workspaceResourceTreeView.reveal( + this._dbNode || accountNode + ); + } + ); + } } diff --git a/Source/commands/api/apiCache.ts b/Source/commands/api/apiCache.ts index 30da342aa..9020478fd 100644 --- a/Source/commands/api/apiCache.ts +++ b/Source/commands/api/apiCache.ts @@ -3,44 +3,68 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; +import { ParsedDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { + ParsedPostgresConnectionString, + parsePostgresConnectionString, +} from "../../postgres/postgresConnectionStrings"; +import { + DatabaseAccountTreeItem, + DatabaseTreeItem, +} from "../../vscode-cosmosdb.api"; /** * This cache is used to speed up api calls from other extensions to the Cosmos DB extension * For now, it only helps on a per-session basis */ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = new Map(); +const sessionCache: Map = + new Map(); -export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { - sessionCache.set(parsedCS.fullId, treeItem); +export function cacheTreeItem( + parsedCS: ParsedConnectionString, + treeItem: DatabaseAccountTreeItem | DatabaseTreeItem +): void { + sessionCache.set(parsedCS.fullId, treeItem); } -export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); +export function tryGetTreeItemFromCache( + parsedCS: ParsedConnectionString +): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { + return sessionCache.get(parsedCS.fullId); } -export function removeTreeItemFromCache(expected: ParsedConnectionString): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); - } else { - actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); - } - if (actual && (actual.accountId === expected.accountId)) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } +export function removeTreeItemFromCache( + expected: ParsedConnectionString +): void { + if (!expected.databaseName) { + // If parsedCS represents an account, remove the account and any databases that match that account + for (const [key, value] of sessionCache.entries()) { + let actual: ParsedConnectionString | undefined; + if (expected instanceof ParsedPostgresConnectionString) { + actual = parsePostgresConnectionString(value.connectionString); + } else if (expected instanceof ParsedMongoConnectionString) { + actual = new ParsedMongoConnectionString( + value.connectionString, + value.hostName, + value.port, + undefined + ); + } else { + actual = new ParsedDocDBConnectionString( + value.connectionString, + value.hostName, + value.port, + undefined + ); + } + if (actual && actual.accountId === expected.accountId) { + sessionCache.delete(key); + } + } + } else { + sessionCache.delete(expected.fullId); + } } diff --git a/Source/commands/api/findTreeItem.ts b/Source/commands/api/findTreeItem.ts index 088413e52..d7e0f0d01 100644 --- a/Source/commands/api/findTreeItem.ts +++ b/Source/commands/api/findTreeItem.ts @@ -3,144 +3,223 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -export async function findTreeItem(query: TreeItemQuery): Promise { - return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, 'connectionString'); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = await rootNode.getCachedChildren(context); - result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - }); +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { + createPostgresConnectionString, + parsePostgresConnectionString, +} from "../../postgres/postgresConnectionStrings"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { SubscriptionTreeItem } from "../../tree/SubscriptionTreeItem"; +import { nonNullProp } from "../../utils/nonNull"; +import { + DatabaseAccountTreeItem, + DatabaseTreeItem, + TreeItemQuery, +} from "../../vscode-cosmosdb.api"; +import { cacheTreeItem, tryGetTreeItemFromCache } from "./apiCache"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; + +export async function findTreeItem( + query: TreeItemQuery +): Promise { + return await callWithTelemetryAndErrorHandling( + "api.findTreeItem", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + + let parsedCS: ParsedConnectionString; + if (query.postgresData) { + const postgresData = query.postgresData; + const connectionString: string = createPostgresConnectionString( + postgresData.hostName, + postgresData.port, + postgresData.username, + postgresData.password, + postgresData.databaseName + ); + parsedCS = parsePostgresConnectionString(connectionString); + } else { + const connectionString = nonNullProp(query, "connectionString"); + if (/^mongodb[^:]*:\/\//i.test(connectionString)) { + parsedCS = + await parseMongoConnectionString(connectionString); + } else if (/^postgres:\/\//i.test(connectionString)) { + parsedCS = parsePostgresConnectionString(connectionString); + } else { + parsedCS = parseDocDBConnectionString(connectionString); + } + } + + const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account + + // 1. Get result from cache if possible + let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = + tryGetTreeItemFromCache(parsedCS); + + // 2. Search attached accounts (do this before subscriptions because it's faster) + if (!result) { + const attachedDbAccounts = + await ext.attachedAccountsNode.getCachedChildren(context); + result = await searchDbAccounts( + attachedDbAccounts, + parsedCS, + context, + maxTime + ); + } + + // 3. Search subscriptions + if (!result) { + const rootNodes = await ext.rgApi.appResourceTree.getChildren(); + for (const rootNode of rootNodes) { + if (Date.now() > maxTime) { + break; + } + + if (rootNode instanceof SubscriptionTreeItem) { + const dbAccounts = + await rootNode.getCachedChildren(context); + result = await searchDbAccounts( + dbAccounts, + parsedCS, + context, + maxTime + ); + if (result) { + break; + } + } + } + } + + // 4. If all else fails, just attach a new node + if (!result) { + if (parsedCS.databaseName) { + result = new DatabaseTreeItemInternal( + parsedCS, + parsedCS.databaseName + ); + } else { + result = new DatabaseAccountTreeItemInternal(parsedCS); + } + } + + cacheTreeItem(parsedCS, result); + + return result; + } + ); } -async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); - } - if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); - } else { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); - } - - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); - } else { - return new DatabaseAccountTreeItemInternal(expected, dbAccount); - } - - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; +async function searchDbAccounts( + dbAccounts: AzExtTreeItem[], + expected: ParsedConnectionString, + context: IActionContext, + maxTime: number +): Promise { + try { + for (const dbAccount of dbAccounts) { + if (Date.now() > maxTime) { + return undefined; + } + + let actual: ParsedConnectionString; + if (dbAccount instanceof MongoAccountTreeItem) { + actual = await parseMongoConnectionString( + dbAccount.connectionString + ); + } else if (dbAccount instanceof DocDBAccountTreeItemBase) { + actual = parseDocDBConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof PostgresServerTreeItem) { + actual = dbAccount.partialConnectionString; + } else { + return undefined; + } + + if (expected.accountId === actual.accountId) { + if (expected.databaseName) { + const dbs = await dbAccount.getCachedChildren(context); + for (const db of dbs) { + if ( + (db instanceof MongoDatabaseTreeItem || + db instanceof DocDBDatabaseTreeItemBase) && + expected.databaseName === db.databaseName + ) { + return new DatabaseTreeItemInternal( + expected, + expected.databaseName, + dbAccount, + db + ); + } + if ( + db instanceof PostgresDatabaseTreeItem && + dbAccount instanceof PostgresServerTreeItem && + expected.databaseName === db.databaseName + ) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal( + fullConnectionString, + expected.databaseName, + dbAccount, + db + ); + } + } + + // We found the right account - just not the db. In this case we can still 'reveal' the account + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal( + fullConnectionString, + expected.databaseName, + dbAccount + ); + } else { + return new DatabaseTreeItemInternal( + expected, + expected.databaseName, + dbAccount + ); + } + } + + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseAccountTreeItemInternal( + fullConnectionString, + dbAccount + ); + } else { + return new DatabaseAccountTreeItemInternal( + expected, + dbAccount + ); + } + } + } + } catch (error) { + // Swallow all errors to avoid blocking the db account search + // https://github.com/microsoft/vscode-cosmosdb/issues/966 + } + + return undefined; } diff --git a/Source/commands/api/pickTreeItem.ts b/Source/commands/api/pickTreeItem.ts index dc84ce55a..f67ab039d 100644 --- a/Source/commands/api/pickTreeItem.ts +++ b/Source/commands/api/pickTreeItem.ts @@ -3,98 +3,146 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; -import { databaseAccountType } from '../../constants'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { localize } from '../../utils/localize'; -import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { PickAppResourceOptions } from "@microsoft/vscode-azext-utils/hostapi"; +import { databaseAccountType } from "../../constants"; +import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItem } from "../../docdb/tree/DocDBDatabaseTreeItem"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { GraphDatabaseTreeItem } from "../../graph/tree/GraphDatabaseTreeItem"; +import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { localize } from "../../utils/localize"; +import { + AzureDatabasesApiType, + DatabaseAccountTreeItem, + DatabaseTreeItem, + PickTreeItemOptions, +} from "../../vscode-cosmosdb.api"; +import { cacheTreeItem } from "./apiCache"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; -const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; +const databaseContextValues = [ + MongoDatabaseTreeItem.contextValue, + DocDBDatabaseTreeItem.contextValue, + GraphDatabaseTreeItem.contextValue, + PostgresDatabaseTreeItem.contextValue, +]; function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case 'Mongo': - return MongoDatabaseTreeItem.contextValue; - case 'SQL': - return DocDBDatabaseTreeItem.contextValue; - case 'Graph': - return GraphDatabaseTreeItem.contextValue; - case 'Postgres': - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } + switch (apiType) { + case "Mongo": + return MongoDatabaseTreeItem.contextValue; + case "SQL": + return DocDBDatabaseTreeItem.contextValue; + case "Graph": + return GraphDatabaseTreeItem.contextValue; + case "Postgres": + return PostgresDatabaseTreeItem.contextValue; + default: + throw new RangeError(`Unsupported api type "${apiType}".`); + } } +export async function pickTreeItem( + pickTreeOptions: PickTreeItemOptions +): Promise { + return await callWithTelemetryAndErrorHandling( + "api.pickTreeItem", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; -export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { - return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + const options: PickAppResourceOptions = {}; + switch (pickTreeOptions.resourceType) { + case "Database": + options.filter = { type: databaseAccountType }; + options.expectedChildContextValue = pickTreeOptions.apiType + ? pickTreeOptions.apiType.map(getDatabaseContextValue) + : databaseContextValues; + break; + case "DatabaseAccount": + options.filter = { type: databaseAccountType }; + break; + default: + throw new RangeError( + `Unsupported resource type "${pickTreeOptions.resourceType}".` + ); + } - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case 'Database': - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType ? - pickTreeOptions.apiType.map(getDatabaseContextValue) : - databaseContextValues; - break; - case 'DatabaseAccount': - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); - } + const pickedItem = await ext.rgApi.pickAppResource( + context, + options + ); - const pickedItem = await ext.rgApi.pickAppResource(context, options); + let parsedCS: ParsedConnectionString; + let accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem; + let databaseNode: + | MongoDatabaseTreeItem + | DocDBDatabaseTreeItemBase + | PostgresDatabaseTreeItem + | undefined; + if (pickedItem instanceof MongoAccountTreeItem) { + parsedCS = await parseMongoConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem; + } else if (pickedItem instanceof DocDBAccountTreeItemBase) { + parsedCS = parseDocDBConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem; + } else if (pickedItem instanceof PostgresServerTreeItem) { + parsedCS = await pickedItem.getFullConnectionString(); + accountNode = pickedItem; + } else if (pickedItem instanceof MongoDatabaseTreeItem) { + parsedCS = await parseMongoConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { + parsedCS = parseDocDBConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof PostgresDatabaseTreeItem) { + parsedCS = await pickedItem.parent.getFullConnectionString(); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else { + throw new RangeError( + localize( + "invalidItem", + 'Invalid item "{0}".', + pickedItem.constructor.name + ) + ); + } - let parsedCS: ParsedConnectionString; - let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; - let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); - } - - const result = databaseNode ? - new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : - new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - }); + const result = databaseNode + ? new DatabaseTreeItemInternal( + parsedCS, + databaseNode.databaseName, + accountNode, + databaseNode + ) + : new DatabaseAccountTreeItemInternal(parsedCS, accountNode); + cacheTreeItem(parsedCS, result); + return result; + } + ); } diff --git a/Source/commands/api/revealTreeItem.ts b/Source/commands/api/revealTreeItem.ts index d13589351..185ff340c 100644 --- a/Source/commands/api/revealTreeItem.ts +++ b/Source/commands/api/revealTreeItem.ts @@ -3,14 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { ext } from "../../extensionVariables"; export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); - } - }); + return await callWithTelemetryAndErrorHandling( + "api.revealTreeItem", + async (context: IActionContext) => { + const node: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem(resourceId, { + ...context, + loadAll: true, + }); + if (node) { + await ext.rgApi.appResourceTreeView.reveal(node, { + select: true, + focus: true, + expand: true, + }); + } + } + ); } diff --git a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts index 1ef9ca645..d409dcc0a 100644 --- a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts @@ -7,13 +7,13 @@ import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } + public async execute(context: IDeleteWizardContext): Promise { + await context.node.deleteTreeItem(context); + } - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } + public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { + return true; + } } diff --git a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts index 762beb96e..e20bafa90 100644 --- a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts @@ -1,13 +1,20 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + ExecuteActivityContext, + IActionContext, + ISubscriptionContext, +} from "@microsoft/vscode-azext-utils"; -export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; +export interface IDeleteWizardContext + extends IActionContext, + ExecuteActivityContext { + node: AzExtTreeItem; + deletePostgres: boolean; + resourceGroupToDelete?: string; + subscription: ISubscriptionContext; } diff --git a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts index a90956b30..b862cb33e 100644 --- a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts @@ -3,30 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; -import { localize } from '../../utils/localize'; -import { IDeleteWizardContext } from './IDeleteWizardContext'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; +import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { ext } from "../../extensionVariables"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { getDatabaseAccountNameFromId } from "../../utils/azureUtils"; +import { localize } from "../../utils/localize"; +import { IDeleteWizardContext } from "./IDeleteWizardContext"; -export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await deletePromise; - const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } else { - await deletePromise; - } +export async function deleteCosmosDBAccount( + context: IDeleteWizardContext, + node: AzExtTreeItem +): Promise { + const client: CosmosDBManagementClient = await createCosmosDBClient([ + context, + node.subscription, + ]); + const resourceGroup: string = getResourceGroupFromId(node.fullId); + const accountName: string = getDatabaseAccountNameFromId(node.fullId); + const deletePromise = client.databaseAccounts.beginDeleteAndWait( + resourceGroup, + accountName + ); + if (!context.suppressNotification) { + const deletingMessage: string = `Deleting account "${accountName}"...`; + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: deletingMessage, + }, + async () => { + await deletePromise; + const deleteMessage: string = localize( + "deleteAccountMsg", + `Successfully deleted account "{0}".`, + accountName + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + } + ); + } else { + await deletePromise; + } } diff --git a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts index 4792710d4..ac6857848 100644 --- a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts @@ -3,35 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + AzureWizard, + DeleteConfirmationStep, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { createActivityContext } from "../../utils/activityUtils"; import { localize } from "../../utils/localize"; import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; +export async function deleteDatabaseAccount( + context: IActionContext, + node: AzExtTreeItem, + isPostgres: boolean = false +): Promise { + const wizardContext: IDeleteWizardContext = Object.assign(context, { + node, + deletePostgres: isPostgres, + subscription: node.subscription, + ...(await createActivityContext()), + }); -export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()) - }); + const title = wizardContext.deletePostgres + ? localize("deletePoSer", 'Delete Postgres Server "{0}"', node.label) + : localize("deleteDbAcc", 'Delete Database Account "{0}"', node.label); - const title = wizardContext.deletePostgres ? - localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : - localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) + const confirmationMessage = wizardContext.deletePostgres + ? localize( + "deleteAccountConfirm", + 'Are you sure you want to delete server "{0}" and its contents?', + node.label + ) + : localize( + "deleteAccountConfirm", + 'Are you sure you want to delete account "{0}" and its contents?', + node.label + ); - const confirmationMessage = wizardContext.deletePostgres ? - localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : - localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); + const wizard = new AzureWizard(wizardContext, { + title, + promptSteps: [new DeleteConfirmationStep(confirmationMessage)], + executeSteps: [new DatabaseAccountDeleteStep()], + }); - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()] - }); - - await wizard.prompt(); - await wizard.execute(); + await wizard.prompt(); + await wizard.execute(); } diff --git a/Source/commands/importDocuments.ts b/Source/commands/importDocuments.ts index bd4c83e3f..305af31eb 100644 --- a/Source/commands/importDocuments.ts +++ b/Source/commands/importDocuments.ts @@ -3,161 +3,209 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from '@azure/cosmos'; -import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { cosmosMongoFilter, sqlFilter } from '../constants'; -import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; -import { ext } from '../extensionVariables'; -import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { getRootPath } from '../utils/workspacUtils'; +import { ItemDefinition } from "@azure/cosmos"; +import { IActionContext, parseError } from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import * as vscode from "vscode"; +import { cosmosMongoFilter, sqlFilter } from "../constants"; +import { DocDBCollectionTreeItem } from "../docdb/tree/DocDBCollectionTreeItem"; +import { ext } from "../extensionVariables"; +import { MongoCollectionTreeItem } from "../mongo/tree/MongoCollectionTreeItem"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { getRootPath } from "../utils/workspacUtils"; -export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); - ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents..." - }, - async (progress) => { - uris = nonNullValue(uris, 'uris'); - collectionNode = nonNullValue(collectionNode, 'collectionNode'); +export async function importDocuments( + context: IActionContext, + uris: vscode.Uri[] | undefined, + collectionNode: + | MongoCollectionTreeItem + | DocDBCollectionTreeItem + | undefined +): Promise { + if (!uris) { + uris = await askForDocuments(context); + } + const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 + uris = uris.filter((uri) => { + if (uri.fsPath.toLocaleLowerCase().endsWith(".json")) { + return true; + } else { + ignoredUris.push(uri); + return false; + } + }); + if (ignoredUris.length) { + ext.outputChannel.appendLog( + `Ignoring the following files which are not json:` + ); + ignoredUris.forEach((uri) => + ext.outputChannel.appendLine(`${uri.fsPath}`) + ); + ext.outputChannel.show(); + } + if (!collectionNode) { + collectionNode = await ext.rgApi.pickAppResource< + MongoCollectionTreeItem | DocDBCollectionTreeItem + >(context, { + filter: [cosmosMongoFilter, sqlFilter], + expectedChildContextValue: [ + MongoCollectionTreeItem.contextValue, + DocDBCollectionTreeItem.contextValue, + ], + }); + } + let result: string; + result = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Importing documents...", + }, + async (progress) => { + uris = nonNullValue(uris, "uris"); + collectionNode = nonNullValue(collectionNode, "collectionNode"); - progress.report({ increment: 20, message: "Parsing documents for errors" }); - const documents = await parseDocuments(uris); - progress.report({ increment: 30, message: "Parsed documents. Importing" }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo(collectionNode, documents); - } else { - result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); + progress.report({ + increment: 20, + message: "Parsing documents for errors", + }); + const documents = await parseDocuments(uris); + progress.report({ + increment: 30, + message: "Parsed documents. Importing", + }); + if (collectionNode instanceof MongoCollectionTreeItem) { + result = await insertDocumentsIntoMongo( + collectionNode, + documents + ); + } else { + result = await insertDocumentsIntoDocdb( + collectionNode, + documents, + uris + ); + } + progress.report({ increment: 50, message: "Finished importing" }); + return result; + } + ); - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); + await collectionNode.refresh(context); + await vscode.window.showInformationMessage(result); } async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"] - } - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); + const openDialogOptions: vscode.OpenDialogOptions = { + canSelectMany: true, + openLabel: "Import", + filters: { + JSON: ["json"], + }, + }; + const rootPath: string | undefined = getRootPath(); + if (rootPath) { + openDialogOptions.defaultUri = vscode.Uri.file(rootPath); + } + return await context.ui.showOpenDialog(openDialogOptions); } // eslint-disable-next-line @typescript-eslint/no-explicit-any async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let documents: any[] = []; + let errorFoundFlag: boolean = false; + for (const uri of uris) { + let parsed; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + parsed = await fse.readJSON(uri.fsPath); + } catch (e) { + if (!errorFoundFlag) { + errorFoundFlag = true; + ext.outputChannel.appendLog( + "Errors found in documents listed below. Please fix these." + ); + ext.outputChannel.show(); + } + const err = parseError(e); + ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); + } + if (parsed) { + if (Array.isArray(parsed)) { + documents = documents.concat(parsed); + } else { + documents.push(parsed); + } + } + } + if (errorFoundFlag) { + throw new Error( + `Errors found in some documents. Please see the output, fix these and try again.` + ); + } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return documents; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); - erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); - ext.outputChannel.show(); - throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); - } - for (const document of documents) { - const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; +async function insertDocumentsIntoDocdb( + collectionNode: DocDBCollectionTreeItem, + documents: any[], + uris: vscode.Uri[] +): Promise { + const ids: string[] = []; + let i = 0; + const erroneousFiles: vscode.Uri[] = []; + for (i = 0; i < documents.length; i++) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const document: ItemDefinition = documents[i]; + if ( + !collectionNode.documentsTreeItem.documentHasPartitionKey(document) + ) { + erroneousFiles.push(uris[i]); + } + } + if (erroneousFiles.length) { + ext.outputChannel.appendLog( + `The following documents do not contain the required partition key:` + ); + erroneousFiles.forEach((file) => + ext.outputChannel.appendLine(file.path) + ); + ext.outputChannel.show(); + throw new Error( + `See output for list of documents that do not contain the partition key '${ + nonNullProp(collectionNode, "partitionKey").paths[0] + }' required by collection '${collectionNode.label}'` + ); + } + for (const document of documents) { + const retrieved: ItemDefinition = + await collectionNode.documentsTreeItem.createDocument(document); + if (retrieved.id) { + ids.push(retrieved.id); + } + } + const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; + for (const id of ids) { + ext.outputChannel.appendLine(`Inserted document: ${id}`); + } + return result; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; +async function insertDocumentsIntoMongo( + node: MongoCollectionTreeItem, + documents: any[] +): Promise { + let output = ""; + const parsed = await node.collection.insertMany(documents); + if (parsed.result && parsed.result.ok) { + output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; + for (const inserted of Object.values(parsed.insertedIds)) { + ext.outputChannel.appendLine(`Inserted document: ${inserted}`); + } + } + return output; } diff --git a/Source/constants.ts b/Source/constants.ts index 0e6a4a14e..4d43ec018 100644 --- a/Source/constants.ts +++ b/Source/constants.ts @@ -5,47 +5,62 @@ export const isWindows: boolean = /^win/.test(process.platform); -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; -import { ext } from './extensionVariables'; +import * as assert from "assert"; +import * as fs from "fs"; +import * as path from "path"; +import { + CoreExperience, + GremlinExperience, + MongoExperience, + TableExperience, +} from "./AzureDBExperiences"; +import { ext } from "./extensionVariables"; export namespace Links { - export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; + export const LocalConnectionDebuggingTips: string = + "https://aka.ms/AA5zah5"; } export interface IThemedIconPath { - light: string; - dark: string; + light: string; + dark: string; } export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'light', iconName), - dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), "icons", "light", iconName), + dark: path.join(getResourcesPath(), "icons", "dark", iconName), + }; + assert(fs.existsSync(a.light)); + return a; } export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), - dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join( + getResourcesPath(), + "icons", + "theme-agnostic", + iconName + ), + dark: path.join( + getResourcesPath(), + "icons", + "theme-agnostic", + iconName + ), + }; + assert(fs.existsSync(a.light)); + return a; } export function getResourcesPath(): string { - return ext.context.asAbsolutePath('resources'); + return ext.context.asAbsolutePath("resources"); } export const doubleClickDebounceDelay = 500; //milliseconds -export const defaultStoredProcedure = - `function sample(prefix) { +export const defaultStoredProcedure = `function sample(prefix) { var collection = getContext().getCollection(); // Query documents and take 1st item. @@ -70,67 +85,69 @@ export const defaultStoredProcedure = }); if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};` ; +};`; -export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; +export const emulatorPassword = + "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; // https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = 'test'; +export const testDb: string = "test"; -export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; -export const postgresLanguageId: string = 'postgres'; +export const connectedPostgresKey: string = + "ms-azuretools.vscode-azuredatabases.connectedPostgresDB"; +export const postgresLanguageId: string = "postgres"; export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = 'query'; -export const postgresDefaultPort = '5432'; -export const postgresDefaultDatabase = 'postgres'; -export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; +export const postgresBaseFileName: string = "query"; +export const postgresDefaultPort = "5432"; +export const postgresDefaultDatabase = "postgres"; +export const SERVERLESS_CAPABILITY_NAME = "EnableServerless"; -export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; +export const databaseAccountType = "Microsoft.DocumentDB/databaseAccounts"; export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag - } + type: databaseAccountType, + kind: MongoExperience.kind, + tags: { + defaultExperience: mongoDefaultExperienceTag, + }, }; -export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; +export const gremlinDefaultExperienceTag = "Gremlin (graph)"; export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag - } + type: databaseAccountType, + kind: GremlinExperience.kind, + tags: { + defaultExperience: gremlinDefaultExperienceTag, + }, }; -export const tableDefaultExperienceTag = 'Azure Table'; +export const tableDefaultExperienceTag = "Azure Table"; export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag - } + type: databaseAccountType, + kind: TableExperience.kind, + tags: { + defaultExperience: tableDefaultExperienceTag, + }, }; -export const sqlDefaultExperienceTag = 'Core (SQL)'; +export const sqlDefaultExperienceTag = "Core (SQL)"; export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag - } + type: databaseAccountType, + kind: CoreExperience.kind, + tags: { + defaultExperience: sqlDefaultExperienceTag, + }, }; export const postgresFlexibleFilter = { - type: 'Microsoft.DBforPostgreSQL/flexibleServers' + type: "Microsoft.DBforPostgreSQL/flexibleServers", }; export const postgresSingleFilter = { - type: 'Microsoft.DBForPostgreSQL/servers' + type: "Microsoft.DBForPostgreSQL/servers", }; diff --git a/Source/docdb/docDBConnectionStrings.ts b/Source/docdb/docDBConnectionStrings.ts index 946490d21..3389eeea4 100644 --- a/Source/docdb/docDBConnectionStrings.ts +++ b/Source/docdb/docDBConnectionStrings.ts @@ -3,40 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as url from 'url'; -import { ParsedConnectionString } from '../ParsedConnectionString'; -import { nonNullProp } from '../utils/nonNull'; +import * as url from "url"; +import { ParsedConnectionString } from "../ParsedConnectionString"; +import { nonNullProp } from "../utils/nonNull"; -export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); - const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); - const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); - if (!endpoint || !masterKey) { - throw new Error('Invalid Document DB connection string.'); - } - return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); +export function parseDocDBConnectionString( + connectionString: string +): ParsedDocDBConnectionString { + const endpoint = getPropertyFromConnectionString( + connectionString, + "AccountEndpoint" + ); + const masterKey = getPropertyFromConnectionString( + connectionString, + "AccountKey" + ); + const databaseName = getPropertyFromConnectionString( + connectionString, + "Database" + ); + if (!endpoint || !masterKey) { + throw new Error("Invalid Document DB connection string."); + } + return new ParsedDocDBConnectionString( + connectionString, + endpoint, + masterKey, + databaseName + ); } -function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; +function getPropertyFromConnectionString( + connectionString: string, + property: string +): string | undefined { + const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, "i"); + const match = connectionString.match(regexp); + return match ? match[1] : undefined; } export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - public readonly documentEndpoint: string; - public readonly masterKey: string; + public readonly documentEndpoint: string; + public readonly masterKey: string; - constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; + constructor( + connectionString: string, + endpoint: string, + masterKey: string, + databaseName: string | undefined + ) { + super(connectionString, databaseName); + this.documentEndpoint = endpoint; + this.masterKey = masterKey; - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, 'hostname'); - this.port = nonNullProp(parsedEndpoint, 'port'); - } + const parsedEndpoint = url.parse(endpoint); + this.hostName = nonNullProp(parsedEndpoint, "hostname"); + this.port = nonNullProp(parsedEndpoint, "port"); + } } diff --git a/Source/docdb/getCosmosClient.ts b/Source/docdb/getCosmosClient.ts index 3b285fc9c..f422ec3c2 100644 --- a/Source/docdb/getCosmosClient.ts +++ b/Source/docdb/getCosmosClient.ts @@ -6,14 +6,33 @@ import { CosmosClient } from "@azure/cosmos"; import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; import * as https from "https"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { ext } from "../extensionVariables"; -export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { - - const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; - return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); - +export function getCosmosClient( + endpoint: string, + key: string, + isEmulator: boolean | undefined +): CosmosClient { + const vscodeStrictSSL: boolean | undefined = vscode.workspace + .getConfiguration() + .get(ext.settingsKeys.vsCode.proxyStrictSSL); + const enableEndpointDiscovery: boolean | undefined = vscode.workspace + .getConfiguration() + .get(ext.settingsKeys.enableEndpointDiscovery); + const connectionPolicy = { + enableEndpointDiscovery: + enableEndpointDiscovery === undefined + ? true + : enableEndpointDiscovery, + }; + return new CosmosClient({ + endpoint, + key, + userAgentSuffix: appendExtensionUserAgent(), + agent: new https.Agent({ + rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL, + }), + connectionPolicy: connectionPolicy, + }); } diff --git a/Source/docdb/registerDocDBCommands.ts b/Source/docdb/registerDocDBCommands.ts index 5eb7545e4..a8f29c69d 100644 --- a/Source/docdb/registerDocDBCommands.ts +++ b/Source/docdb/registerDocDBCommands.ts @@ -3,7 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + IActionContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; import { commands } from "vscode"; import { doubleClickDebounceDelay, sqlFilter } from "../constants"; import { ext } from "../extensionVariables"; @@ -16,89 +21,170 @@ import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeI import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openDocument", documentNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); - } - const childNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - - } - await node.deleteTreeItem(context); - }); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBDatabase", + createDocDBDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBCollection", + createDocDBCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBDocument", + async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDocumentsTreeItem.contextValue + ); + } + const documentNode = ( + await node.createChild(context) + ); + await commands.executeCommand( + "cosmosDB.openDocument", + documentNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProceduresTreeItem + ) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProceduresTreeItem.contextValue + ); + } + const childNode = await node.createChild(context); + await commands.executeCommand( + "cosmosDB.openStoredProcedure", + childNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBDatabase", + deleteDocDBDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBCollection", + deleteDocDBCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProcedureTreeItem + ) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProcedureTreeItem.contextValue + ); + } + await ext.fileSystem.showTextDocument(node); + }, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBDocument", + async (context: IActionContext, node?: DocDBDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDocumentTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProcedureTreeItem + ) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProcedureTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); } -export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); - await databaseNode.createChild(context); +export async function createDocDBDatabase( + context: IActionContext, + node?: DocDBAccountTreeItem +): Promise { + if (!node) { + node = await pickDocDBAccount(context); + } + const databaseNode: DocDBDatabaseTreeItem = ( + await node.createChild(context) + ); + await databaseNode.createChild(context); } -export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.createChild(context); +export async function createDocDBCollection( + context: IActionContext, + node?: DocDBDatabaseTreeItem +): Promise { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDatabaseTreeItem.contextValue + ); + } + await node.createChild(context); } -export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteDocDBDatabase( + context: IActionContext, + node?: DocDBDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteDocDBCollection( + context: IActionContext, + node?: DocDBCollectionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - sqlFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickDocDBAccount( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [sqlFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/docdb/tree/DocDBAccountTreeItem.ts b/Source/docdb/tree/DocDBAccountTreeItem.ts index 0cee7ed06..242af5546 100644 --- a/Source/docdb/tree/DocDBAccountTreeItem.ts +++ b/Source/docdb/tree/DocDBAccountTreeItem.ts @@ -3,35 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { DatabaseDefinition, Resource } from "@azure/cosmos"; +import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBDocumentServer"; + public contextValue: string = DocDBAccountTreeItem.contextValue; - public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } + public initChild( + resource: DatabaseDefinition & Resource + ): DocDBDatabaseTreeItem { + this.valuesToMask.push(resource._rid, resource._self); + return new DocDBDatabaseTreeItem(this, resource); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case DocDBDatabaseTreeItem.contextValue: + case DocDBCollectionTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case DocDBDocumentsTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/docdb/tree/DocDBAccountTreeItemBase.ts b/Source/docdb/tree/DocDBAccountTreeItemBase.ts index da9eec6b7..2984b29ef 100644 --- a/Source/docdb/tree/DocDBAccountTreeItemBase.ts +++ b/Source/docdb/tree/DocDBAccountTreeItemBase.ts @@ -3,93 +3,139 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { rejectOnTimeout } from '../../utils/timeout'; -import { getCosmosClient } from '../getCosmosClient'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { + CosmosClient, + DatabaseDefinition, + DatabaseResponse, + FeedOptions, + QueryIterator, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { + SERVERLESS_CAPABILITY_NAME, + getThemeAgnosticIconPath, +} from "../../constants"; +import { nonNullProp } from "../../utils/nonNull"; +import { rejectOnTimeout } from "../../utils/timeout"; +import { getCosmosClient } from "../getCosmosClient"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class provides common logic for DocumentDB, Graph, and Table accounts * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; +export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase< + DatabaseDefinition & Resource +> { + public readonly label: string; + public readonly childTypeLabel: string = "Database"; + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + endpoint: string, + masterKey: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super(parent); + this.id = id; + this.label = label; + this.root = { + endpoint, + masterKey, + isEmulator, + getCosmosClient: () => + getCosmosClient(endpoint, masterKey, isEmulator), + }; - constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) - }; + this.valuesToMask.push(id, endpoint, masterKey); + } - this.valuesToMask.push(id, endpoint, masterKey); - } + public get connectionString(): string { + return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; + } - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("CosmosDBAccount.svg"); + } - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } + public get isServerless(): boolean { + return this.databaseAccount?.capabilities + ? this.databaseAccount.capabilities.some( + (cap) => cap.name === SERVERLESS_CAPABILITY_NAME + ) + : false; + } - public get isServerless(): boolean { - return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return client.databases.readAll(feedOptions); + } - } + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + validateInput: validateDatabaseName, + stepName: "createDatabase", + }); - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.databases.readAll(feedOptions); - } + const client = this.root.getCosmosClient(); + const database: DatabaseResponse = await client.databases.create({ + id: databaseName, + }); + return this.initChild(nonNullProp(database, "resource")); + } - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: 'Database Name', - validateInput: validateDatabaseName, - stepName: 'createDatabase' - }); + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (this.root.isEmulator) { + const unableToReachEmulatorMessage: string = + "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; + return await rejectOnTimeout( + 2000, + () => super.loadMoreChildrenImpl(clearCache), + unableToReachEmulatorMessage + ); + } else { + return await super.loadMoreChildrenImpl(clearCache); + } + } - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ id: databaseName }); - return this.initChild(nonNullProp(database, 'resource')); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } } function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; + if (!name || name.length < 1 || name.length > 255) { + return "Name has to be between 1 and 255 chars long"; + } + if (name.endsWith(" ")) { + return "Database name cannot end with space"; + } + if (/[/\\?#=]/.test(name)) { + return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBCollectionTreeItem.ts b/Source/docdb/tree/DocDBCollectionTreeItem.ts index 987bbe3b4..8849bee34 100644 --- a/Source/docdb/tree/DocDBCollectionTreeItem.ts +++ b/Source/docdb/tree/DocDBCollectionTreeItem.ts @@ -3,90 +3,115 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { + Container, + ContainerDefinition, + CosmosClient, + PartitionKeyDefinition, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * Represents a DocumentDB collection */ export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - } + public static contextValue: string = "cosmosDBDocumentCollection"; + public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; + public readonly documentsTreeItem: DocDBDocumentsTreeItem; + public readonly parent: DocDBDatabaseTreeItem; + + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + constructor( + parent: DocDBDatabaseTreeItem, + private _container: ContainerDefinition & Resource + ) { + super(parent); + this.parent = parent; + this.documentsTreeItem = new DocDBDocumentsTreeItem(this); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( + this + ); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._container.id; + } + + public get label(): string { + return this._container.id; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get link(): string { + return this._container._self; + } + + public get partitionKey(): PartitionKeyDefinition | undefined { + return this._container.partitionKey; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteCollection" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return [this.documentsTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public pickTreeItemImpl( + expectedContextValues: (string | RegExp)[] + ): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case DocDBDocumentsTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + return this.documentsTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getDatabaseClient(client).container(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItem.ts b/Source/docdb/tree/DocDBDatabaseTreeItem.ts index ee8c23694..b51504cc2 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItem.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItem.ts @@ -3,20 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; +import { + ContainerDefinition, + CosmosClient, + Database, + Resource, +} from "@azure/cosmos"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDatabaseTreeItemBase } from "./DocDBDatabaseTreeItemBase"; export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Collection'; + public static contextValue: string = "cosmosDBDocumentDatabase"; + public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; - public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } + public initChild( + container: ContainerDefinition & Resource + ): DocDBCollectionTreeItem { + return new DocDBCollectionTreeItem(this, container); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts index aa7e8d779..15a935e5c 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts @@ -3,12 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { + ContainerDefinition, + ContainerResponse, + CosmosClient, + DatabaseDefinition, + FeedOptions, + QueryIterator, + RequestOptions, + Resource, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; const minThroughputFixed: number = 400; const minThroughputPartitioned: number = 400; @@ -19,143 +34,177 @@ const throughputStepSize = 100; * This class provides common logic for DocumentDB, Graph, and Table databases * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public get id(): string { - return nonNullProp(this._database, 'id'); - } - - public get label(): string { - return nonNullProp(this._database, 'id'); - } - - public get link(): string { - return nonNullProp(this._database, '_self'); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.database(this._database.id).containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl(context: ICreateChildImplContext): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}` - }); - - const containerDefinition: ContainerDefinition = { - id: containerName - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey] - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !(containerDefinition.partitionKey); - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const throughput: number = Number(await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: 'throughputCapacity', - validateInput: (input: string) => validateThroughput(isFixed, input) - })); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, 'resource')); - } - - protected async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address/zipCode' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } +export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase< + ContainerDefinition & Resource +> { + public readonly parent: DocDBAccountTreeItemBase; + private readonly _database: DatabaseDefinition & Resource; + + constructor( + parent: DocDBAccountTreeItemBase, + database: DatabaseDefinition & Resource + ) { + super(parent); + this._database = database; + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("database"); + } + + public get id(): string { + return nonNullProp(this._database, "id"); + } + + public get label(): string { + return nonNullProp(this._database, "id"); + } + + public get link(): string { + return nonNullProp(this._database, "_self"); + } + + public get connectionString(): string { + return this.parent.connectionString.concat(`;Database=${this.id}`); + } + + public get databaseName(): string { + return this._database.id; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return client + .database(this._database.id) + .containers.readAll(feedOptions); + } + + // Delete the database + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteDatabase" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await client.database(this.id).delete(); + } + + // Create a DB collection + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const containerName = await context.ui.showInputBox({ + placeHolder: `Enter an id for your ${this.childTypeLabel}`, + validateInput: validateCollectionName, + stepName: `create${this.childTypeLabel}`, + }); + + const containerDefinition: ContainerDefinition = { + id: containerName, + }; + + const partitionKey = await this.getNewPartitionKey(context); + if (partitionKey) { + containerDefinition.partitionKey = { + paths: [partitionKey], + }; + } + const options: RequestOptions = {}; + + if (!this.parent.isServerless) { + const isFixed: boolean = !containerDefinition.partitionKey; + const minThroughput = isFixed + ? minThroughputFixed + : minThroughputPartitioned; + const throughput: number = Number( + await context.ui.showInputBox({ + value: minThroughput.toString(), + prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, + stepName: "throughputCapacity", + validateInput: (input: string) => + validateThroughput(isFixed, input), + }) + ); + + if (throughput !== 0) { + options.offerThroughput = throughput; + } + } + + context.showCreatingTreeItem(containerName); + const client = this.root.getCosmosClient(); + const container: ContainerResponse = await client + .database(this.id) + .containers.create(containerDefinition, options); + + return this.initChild(nonNullProp(container, "resource")); + } + + protected async getNewPartitionKey( + context: IActionContext + ): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: "Enter the partition key for the collection, or leave blank for fixed size.", + stepName: "partitionKeyForCollection", + validateInput: this.validatePartitionKey, + placeHolder: "e.g. /address/zipCode", + }); + + if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { + partitionKey = "/" + partitionKey; + } + + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + return undefined; + } } -function validateThroughput(isFixed: boolean, input: string): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const value = Number(input); - if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; +function validateThroughput( + isFixed: boolean, + input: string +): string | undefined | null { + if (input === "0") { + return undefined; + } + + try { + const minThroughput = isFixed + ? minThroughputFixed + : minThroughputPartitioned; + const value = Number(input); + if ( + value < minThroughput || + value > maxThroughput || + (value - minThroughput) % throughputStepSize !== 0 + ) { + return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; + } + } catch (err) { + return "Input must be a number"; + } + return undefined; } function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; + if (!name) { + return "Collection name cannot be empty"; + } + if (name.endsWith(" ")) { + return "Collection name cannot end with space"; + } + if (/[/\\?#]/.test(name)) { + return `Collection name cannot contain the characters '\\', '/', '#', '?'`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBDocumentTreeItem.ts b/Source/docdb/tree/DocDBDocumentTreeItem.ts index 1505572d9..408dedfd7 100644 --- a/Source/docdb/tree/DocDBDocumentTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentTreeItem.ts @@ -3,131 +3,171 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { sanitizeId } from './DocDBUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; +import { + CosmosClient, + Item, + ItemDefinition, + RequestOptions, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullProp } from "../../utils/nonNull"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { sanitizeId } from "./DocDBUtils"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; + +const hiddenFields: string[] = [ + "_rid", + "_self", + "_etag", + "_attachments", + "_ts", +]; /** * Represents a Cosmos DB DocumentDB (SQL) document */ -export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openDocument'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error(`The "_self" and "_etag" fields are required to update a document`); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; - const response = await this.getDocumentClient(client).replace(newData, options); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split('/'); - if (fields[0] === '') { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { //Partition Key exists, but this document doesn't have a value - return ''; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); - } +export class DocDBDocumentTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "cosmosDBDocument"; + public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; + public readonly parent: DocDBDocumentsTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + private _label: string; + private _document: ItemDefinition; + + constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { + super(parent); + this._document = document; + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + this.commandId = "cosmosDB.openDocument"; + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); + } + + public get filePath(): string { + return this.label + "-cosmos-document.json"; + } + + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + } + + public get link(): string { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return this.document._self; + } + + get document(): ItemDefinition { + return this._document; + } + + get label(): string { + return this._label; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("file"); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteDocument" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getDocumentClient(client).delete(); + } + + public async getFileContent(): Promise { + const clonedDoc: {} = { ...this.document }; + for (const field of hiddenFields) { + delete clonedDoc[field]; + } + return JSON.stringify(clonedDoc, null, 2); + } + + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const newData = JSON.parse(content); + for (const field of hiddenFields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + newData[field] = this.document[field]; + } + + const client: CosmosClient = this.root.getCosmosClient(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (["_etag"].some((element) => !newData[element])) { + throw new Error( + `The "_self" and "_etag" fields are required to update a document` + ); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const options: RequestOptions = { + accessCondition: { type: "IfMatch", condition: newData._etag }, + }; + const response = await this.getDocumentClient(client).replace( + newData, + options + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this._document = response.resource; + } + } + + private getPartitionKeyValue(): string | undefined | Object { + const partitionKey = this.parent.parent.partitionKey; + if (!partitionKey) { + //Fixed collections -> no partitionKeyValue + return undefined; + } + const fields = partitionKey.paths[0].split("/"); + if (fields[0] === "") { + fields.shift(); + } + let value; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + value = value ? value[field] : this.document[field]; + if (!value) { + //Partition Key exists, but this document doesn't have a value + return ""; + } + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + } + + private getDocumentClient(client: CosmosClient): Item { + return this.parent + .getContainerClient(client) + .item( + nonNullProp(this.document, "id"), + this.getPartitionKeyValue() + ); + } } diff --git a/Source/docdb/tree/DocDBDocumentsTreeItem.ts b/Source/docdb/tree/DocDBDocumentsTreeItem.ts index b8265444d..ec05451e0 100644 --- a/Source/docdb/tree/DocDBDocumentsTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentsTreeItem.ts @@ -3,127 +3,160 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; -import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { + Container, + CosmosClient, + FeedOptions, + ItemDefinition, + ItemResponse, + QueryIterator, +} from "@azure/cosmos"; +import { + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class provides logic for DocumentDB collections */ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = (await this.promptForPartitionKey(context, body)); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); - return nonNullProp(item, 'resource'); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split('/'); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { - const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: 'valueforParititionKey' - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { - //remove leading slash - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split('/'); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } + public static contextValue: string = "cosmosDBDocumentsGroup"; + public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; + public readonly childTypeLabel: string = "Documents"; + public readonly parent: DocDBCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get id(): string { + return "$Documents"; + } + + public get label(): string { + return "Documents"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return this.getContainerClient(client).items.readAll(feedOptions); + } + + public initChild(document: ItemDefinition): DocDBDocumentTreeItem { + return new DocDBDocumentTreeItem(this, document); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + let docID = await context.ui.showInputBox({ + prompt: "Enter a document ID or leave blank for a generated ID", + stepName: "createDocument", + }); + + docID = docID.trim(); + let body: ItemDefinition = { id: docID }; + body = await this.promptForPartitionKey(context, body); + context.showCreatingTreeItem(docID); + const item: ItemDefinition = await this.createDocument(body); + + return this.initChild(item); + } + + public async createDocument(body: ItemDefinition): Promise { + const item: ItemResponse = + await this.getContainerClient( + this.root.getCosmosClient() + ).items.create(body); + return nonNullProp(item, "resource"); + } + + public documentHasPartitionKey(doc: Object): boolean { + let interim = doc; + let partitionKey: string | undefined = + this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (!partitionKey) { + return true; + } + if (partitionKey[0] === "/") { + partitionKey = partitionKey.slice(1); + } + const partitionKeyPath = partitionKey.split("/"); + + for (const prop of partitionKeyPath) { + // eslint-disable-next-line no-prototype-builtins + if (interim.hasOwnProperty(prop)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[prop]; + } else { + return false; + } + } + return true; + } + + public async promptForPartitionKey( + context: IActionContext, + body: ItemDefinition + ): Promise { + const partitionKey: string | undefined = + this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (partitionKey) { + const partitionKeyValue: string = await context.ui.showInputBox({ + prompt: `Enter a value for the partition key ("${partitionKey}")`, + stepName: "valueforParititionKey", + }); + // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. + // We need to present the partitionKey value as part of the document contents + Object.assign( + body, + this.createPartitionPathObject(partitionKey, partitionKeyValue) + ); + } + return body; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + // Create a nested Object given the partition key path and value + private createPartitionPathObject( + partitionKey: string, + partitionKeyValue: string + ): Object { + //remove leading slash + if (partitionKey[0] === "/") { + partitionKey = partitionKey.slice(1); + } + const keyPath = partitionKey.split("/"); + const PartitionPath: Object = {}; + let interim: Object = PartitionPath; + let i: number; + for (i = 0; i < keyPath.length - 1; i++) { + interim[keyPath[i]] = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[keyPath[i]]; + } + interim[keyPath[i]] = partitionKeyValue; + return PartitionPath; + } } diff --git a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts index 899eccd27..20ced0d3e 100644 --- a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts @@ -3,74 +3,100 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * Represents a Cosmos DB DocumentDB (SQL) stored procedure */ -export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); +export class DocDBStoredProcedureTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "cosmosDBStoredProcedure"; + public readonly contextValue: string = + DocDBStoredProcedureTreeItem.contextValue; + public readonly cTime: number = Date.now(); + public readonly parent: DocDBStoredProceduresTreeItem; + public mTime: number = Date.now(); - constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openStoredProcedure'; - } + constructor( + parent: DocDBStoredProceduresTreeItem, + public procedure: StoredProcedureDefinition & Resource + ) { + super(parent); + ext.fileSystem.fireChangedEvent(this); + this.commandId = "cosmosDB.openStoredProcedure"; + } - public get root(): IDocDBTreeRoot { - return this.parent.root; - } + public get root(): IDocDBTreeRoot { + return this.parent.root; + } - public get filePath(): string { - return this.label + '-cosmos-stored-procedure.js'; - } + public get filePath(): string { + return this.label + "-cosmos-stored-procedure.js"; + } - public get id(): string { - return this.procedure.id; - } + public get id(): string { + return this.procedure.id; + } - public get label(): string { - return this.procedure.id; - } + public get label(): string { + return this.procedure.id; + } - public get link(): string { - return this.procedure._self; - } + public get link(): string { + return this.procedure._self; + } - public async getFileContent(): Promise { - return typeof this.procedure.body === 'string' ? this.procedure.body : ''; + public async getFileContent(): Promise { + return typeof this.procedure.body === "string" + ? this.procedure.body + : ""; + } - } + public async refreshImpl(): Promise { + ext.fileSystem.fireChangedEvent(this); + } - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + const client = this.root.getCosmosClient(); + const replace = await this.parent + .getContainerClient(client) + .scripts.storedProcedure(this.id) + .replace({ id: this.id, body: content }); + this.procedure = nonNullProp(replace, "resource"); + } - public async writeFileContent(_context: IActionContext, content: string): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, 'resource'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("server-process"); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteStoredProcedure" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.parent + .getContainerClient(client) + .scripts.storedProcedure(this.id) + .delete(); + } } diff --git a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts index 4c3ddfd1a..a869e8a99 100644 --- a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts @@ -3,95 +3,141 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { + Container, + CosmosClient, + FeedOptions, + QueryIterator, + Resource, + StoredProcedureDefinition, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; -import { defaultStoredProcedure } from '../../constants'; -import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { defaultStoredProcedure } from "../../constants"; +import { GraphCollectionTreeItem } from "../../graph/tree/GraphCollectionTreeItem"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class represents the DocumentDB "Stored Procedures" node in the tree */ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = (await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: 'createStoredProcedure', - validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) - })).trim(); - const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; - context.showCreatingTreeItem(spID); - const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, 'resource')); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize("nameLength", "Name has to be between 1 and 255 chars long"); - } - - if (/[/\\?#&]/.test(name)) { - return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); - } - - return undefined; - } + public static contextValue: string = "cosmosDBStoredProceduresGroup"; + public readonly contextValue: string = + DocDBStoredProceduresTreeItem.contextValue; + public readonly childTypeLabel: string = "Stored Procedure"; + public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public initChild( + resource: StoredProcedureDefinition & Resource + ): DocDBStoredProcedureTreeItem { + return new DocDBStoredProcedureTreeItem(this, resource); + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("server-process"); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const client = this.root.getCosmosClient(); + const currStoredProcedureList: AzExtTreeItem[] = + await this.getCachedChildren(context); + const currStoredProcedureNames: string[] = []; + for (const sp of currStoredProcedureList) { + currStoredProcedureNames.push(nonNullProp(sp, "id")); + } + const spID = ( + await context.ui.showInputBox({ + prompt: "Enter a unique stored procedure ID", + stepName: "createStoredProcedure", + validateInput: (name: string) => + this.validateStoredProcedureName( + name, + currStoredProcedureNames + ), + }) + ).trim(); + const body: StoredProcedureDefinition = { + id: spID, + body: defaultStoredProcedure, + }; + context.showCreatingTreeItem(spID); + const sproc = + await this.getContainerClient( + client + ).scripts.storedProcedures.create(body); + + return this.initChild(nonNullProp(sproc, "resource")); + } + + public get id(): string { + return "$StoredProcedures"; + } + + public get label(): string { + return "Stored Procedures"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return this.getContainerClient(client).scripts.storedProcedures.readAll( + feedOptions + ); + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + private validateStoredProcedureName( + name: string, + currStoredProcedureNames: string[] + ): string | undefined { + if (name.length < 1 || name.length > 255) { + return localize( + "nameLength", + "Name has to be between 1 and 255 chars long" + ); + } + + if (/[/\\?#&]/.test(name)) { + return localize( + "illegalChars", + "Name contains illegal chars: /, \\, ?, #, &" + ); + } + if (name[name.length - 1] === " ") { + return localize("endsWithSpace", "Name cannot end with a space."); + } + if (currStoredProcedureNames.includes(name)) { + return localize( + "nameExists", + 'Stored Procedure "{0}" already exists.', + name + ); + } + + return undefined; + } } diff --git a/Source/docdb/tree/DocDBTreeItemBase.ts b/Source/docdb/tree/DocDBTreeItemBase.ts index 4424603ae..0774fbcdc 100644 --- a/Source/docdb/tree/DocDBTreeItemBase.ts +++ b/Source/docdb/tree/DocDBTreeItemBase.ts @@ -3,53 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { CosmosClient, FeedOptions, QueryIterator } from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, +} from "@microsoft/vscode-azext-utils"; +import { getBatchSizeSetting } from "../../utils/workspacUtils"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * This class provides common iteration logic for DocumentDB accounts, databases, and collections */ export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; + public abstract readonly label: string; + public abstract readonly contextValue: string; + public abstract readonly childTypeLabel: string; - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); + private _hasMoreChildren: boolean = true; + private _iterator: QueryIterator | undefined; + private _batchSize: number = getBatchSizeSetting(); - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } - public root: IDocDBTreeRoot; + public root: IDocDBTreeRoot; - public abstract initChild(resource: T): AzExtTreeItem; + public abstract initChild(resource: T): AzExtTreeItem; - public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; + public abstract getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator; - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + } - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); - } + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache || this._iterator === undefined) { + this._hasMoreChildren = true; + const client = this.root.getCosmosClient(); + this._iterator = this.getIterator(client, { + maxItemCount: this._batchSize, + }); + } - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); + const resourceArray: T[] = []; + const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()) + .resources; + if (resourceFeed) { + resourceArray.push(...resourceFeed); + } + this._hasMoreChildren = this._iterator.hasMoreResults(); - this._batchSize *= 2; + this._batchSize *= 2; - return resourceArray.map((resource: T) => this.initChild(resource)); - } + return resourceArray.map((resource: T) => this.initChild(resource)); + } } diff --git a/Source/docdb/tree/DocDBUtils.ts b/Source/docdb/tree/DocDBUtils.ts index 3d45cf950..1a0630d53 100644 --- a/Source/docdb/tree/DocDBUtils.ts +++ b/Source/docdb/tree/DocDBUtils.ts @@ -8,5 +8,5 @@ * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding */ export function sanitizeId(id: string): string { - return id.replace(/\+/g, ' '); + return id.replace(/\+/g, " "); } diff --git a/Source/docdb/tree/IDocDBTreeRoot.ts b/Source/docdb/tree/IDocDBTreeRoot.ts index 9179eb454..6827564c2 100644 --- a/Source/docdb/tree/IDocDBTreeRoot.ts +++ b/Source/docdb/tree/IDocDBTreeRoot.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -7,8 +6,8 @@ import { CosmosClient } from "@azure/cosmos"; export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; + endpoint: string; + masterKey: string; + isEmulator: boolean | undefined; + getCosmosClient(): CosmosClient; } diff --git a/Source/extension.ts b/Source/extension.ts index e68744157..c712fbc4c 100644 --- a/Source/extension.ts +++ b/Source/extension.ts @@ -3,213 +3,409 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; -import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; -import { platform } from 'os'; -import * as vscode from 'vscode'; -import { DatabasesFileSystem } from './DatabasesFileSystem'; -import { findTreeItem } from './commands/api/findTreeItem'; -import { pickTreeItem } from './commands/api/pickTreeItem'; -import { revealTreeItem } from './commands/api/revealTreeItem'; -import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { importDocuments } from './commands/importDocuments'; -import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; -import { registerDocDBCommands } from './docdb/registerDocDBCommands'; -import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; -import { ext } from './extensionVariables'; -import { getResourceGroupsApi } from './getExtensionApi'; -import { registerGraphCommands } from './graph/registerGraphCommands'; -import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; -import { registerMongoCommands } from './mongo/registerMongoCommands'; -import { setConnectedNode } from './mongo/setConnectedNode'; -import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; -import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; -import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; -import { DatabaseResolver } from './resolver/AppResolver'; -import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; -import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; -import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; -import { localize } from './utils/localize'; - -const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; - -export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = 'true'; - activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); - - const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); - ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { - if (platform() !== 'win32') { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); - } - - await ext.attachedAccountsNode.attachEmulator(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh(actionContext, node); - } - }); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { - const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); - if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { - const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); - } - if (node instanceof MongoAccountTreeItem) { - if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments(actionContext, uris || [selectedNode], undefined); - } else { - await importDocuments(actionContext, undefined, selectedNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { - if (!node) { - node = await ext.rgApi.pickAppResource(actionContext, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); - registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); - registerEvent( - 'cosmosDB.onDidChangeConfiguration', - vscode.workspace.onDidChangeConfiguration, - async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { - actionContext.telemetry.properties.isActivationEvent = "true"; - actionContext.errorHandling.suppressDisplay = true; - if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { - await vscode.commands.executeCommand("azureDatabases.refresh"); - } - }); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); - registerReportIssueCommand('azureDatabases.reportIssue'); - }); - - return createApiProvider([{ - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: '1.2.0' - }]); +"use strict"; + +import { registerAzureUtilsExtensionVariables } from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + AzureExtensionApi, + IActionContext, + ITreeItemPickerContext, + apiUtils, + callWithTelemetryAndErrorHandling, + createApiProvider, + createAzExtOutputChannel, + registerCommandWithTreeNodeUnwrapping, + registerErrorHandler, + registerEvent, + registerReportIssueCommand, + registerUIExtensionVariables, +} from "@microsoft/vscode-azext-utils"; +import { AzExtResourceType } from "@microsoft/vscode-azureresources-api"; +import { platform } from "os"; +import * as vscode from "vscode"; +import { DatabasesFileSystem } from "./DatabasesFileSystem"; +import { findTreeItem } from "./commands/api/findTreeItem"; +import { pickTreeItem } from "./commands/api/pickTreeItem"; +import { revealTreeItem } from "./commands/api/revealTreeItem"; +import { deleteDatabaseAccount } from "./commands/deleteDatabaseAccount/deleteDatabaseAccount"; +import { importDocuments } from "./commands/importDocuments"; +import { + cosmosGremlinFilter, + cosmosMongoFilter, + cosmosTableFilter, + doubleClickDebounceDelay, + sqlFilter, +} from "./constants"; +import { registerDocDBCommands } from "./docdb/registerDocDBCommands"; +import { DocDBAccountTreeItem } from "./docdb/tree/DocDBAccountTreeItem"; +import { DocDBAccountTreeItemBase } from "./docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBCollectionTreeItem } from "./docdb/tree/DocDBCollectionTreeItem"; +import { DocDBDocumentTreeItem } from "./docdb/tree/DocDBDocumentTreeItem"; +import { ext } from "./extensionVariables"; +import { getResourceGroupsApi } from "./getExtensionApi"; +import { registerGraphCommands } from "./graph/registerGraphCommands"; +import { GraphAccountTreeItem } from "./graph/tree/GraphAccountTreeItem"; +import { registerMongoCommands } from "./mongo/registerMongoCommands"; +import { setConnectedNode } from "./mongo/setConnectedNode"; +import { MongoAccountTreeItem } from "./mongo/tree/MongoAccountTreeItem"; +import { MongoCollectionTreeItem } from "./mongo/tree/MongoCollectionTreeItem"; +import { MongoDocumentTreeItem } from "./mongo/tree/MongoDocumentTreeItem"; +import { registerPostgresCommands } from "./postgres/commands/registerPostgresCommands"; +import { DatabaseResolver } from "./resolver/AppResolver"; +import { DatabaseWorkspaceProvider } from "./resolver/DatabaseWorkspaceProvider"; +import { TableAccountTreeItem } from "./table/tree/TableAccountTreeItem"; +import { AttachedAccountSuffix } from "./tree/AttachedAccountsTreeItem"; +import { SubscriptionTreeItem } from "./tree/SubscriptionTreeItem"; +import { localize } from "./utils/localize"; + +const cosmosDBTopLevelContextValues: string[] = [ + GraphAccountTreeItem.contextValue, + DocDBAccountTreeItem.contextValue, + TableAccountTreeItem.contextValue, + MongoAccountTreeItem.contextValue, +]; + +export async function activateInternal( + context: vscode.ExtensionContext, + perfStats: { loadStartTime: number; loadEndTime: number }, + ignoreBundle?: boolean +): Promise { + ext.context = context; + ext.ignoreBundle = ignoreBundle; + + ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); + context.subscriptions.push(ext.outputChannel); + registerUIExtensionVariables(ext); + registerAzureUtilsExtensionVariables(ext); + + await callWithTelemetryAndErrorHandling( + "cosmosDB.activate", + async (activateContext: IActionContext) => { + activateContext.telemetry.properties.isActivationEvent = "true"; + activateContext.telemetry.measurements.mainFileLoad = + (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; + + ext.secretStorage = context.secrets; + + ext.rgApi = await getResourceGroupsApi(); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.AzureCosmosDb, + new DatabaseResolver() + ); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.PostgresqlServersStandard, + new DatabaseResolver() + ); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.PostgresqlServersFlexible, + new DatabaseResolver() + ); + + const workspaceRootTreeItem = ( + ext.rgApi.workspaceResourceTree as unknown as { + _rootTreeItem: AzExtParentTreeItem; + } + )._rootTreeItem; + const databaseWorkspaceProvider = new DatabaseWorkspaceProvider( + workspaceRootTreeItem + ); + ext.rgApi.registerWorkspaceResourceProvider( + "AttachedDatabaseAccount", + databaseWorkspaceProvider + ); + + ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); + + registerDocDBCommands(); + registerGraphCommands(); + registerPostgresCommands(); + registerMongoCommands(); + + context.subscriptions.push( + vscode.workspace.registerFileSystemProvider( + DatabasesFileSystem.scheme, + ext.fileSystem + ) + ); + + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.selectSubscriptions", + () => + vscode.commands.executeCommand( + "azure-account.selectSubscriptions" + ) + ); + + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.createServer", + createServer + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteAccount", + deleteAccount + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.attachDatabaseAccount", + async (actionContext: IActionContext) => { + await ext.attachedAccountsNode.attachNewAccount( + actionContext + ); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.attachEmulator", + async (actionContext: IActionContext) => { + if (platform() !== "win32") { + actionContext.errorHandling.suppressReportIssue = true; + throw new Error( + localize( + "emulatorNotSupported", + "The Cosmos DB emulator is only supported on Windows." + ) + ); + } + + await ext.attachedAccountsNode.attachEmulator( + actionContext + ); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.refresh", + async (actionContext: IActionContext, node?: AzExtTreeItem) => { + if (node) { + await node.refresh(actionContext); + } else { + await ext.rgApi.appResourceTree.refresh( + actionContext, + node + ); + } + } + ); + + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.detachDatabaseAccount", + async ( + actionContext: IActionContext & ITreeItemPickerContext, + node?: AzExtTreeItem + ) => { + const children = + await ext.attachedAccountsNode.loadAllChildren( + actionContext + ); + if ( + children[0].contextValue === + "cosmosDBAttachDatabaseAccount" + ) { + const message = localize( + "noAttachedAccounts", + "There are no Attached Accounts." + ); + void vscode.window.showInformationMessage(message); + } else { + if (!node) { + node = + await ext.rgApi.workspaceResourceTree.showTreeItemPicker( + cosmosDBTopLevelContextValues.map( + (val: string) => + (val += AttachedAccountSuffix) + ), + actionContext + ); + } + if (node instanceof MongoAccountTreeItem) { + if ( + ext.connectedMongoDB && + node.fullId === + ext.connectedMongoDB.parent.fullId + ) { + setConnectedNode(undefined); + await node.refresh(actionContext); + } + } + await ext.attachedAccountsNode.detach(node); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.importDocument", + async ( + actionContext: IActionContext, + selectedNode: + | vscode.Uri + | MongoCollectionTreeItem + | DocDBCollectionTreeItem, + uris: vscode.Uri[] + ) => { + if (selectedNode instanceof vscode.Uri) { + await importDocuments( + actionContext, + uris || [selectedNode], + undefined + ); + } else { + await importDocuments( + actionContext, + undefined, + selectedNode + ); + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.copyConnectionString", + cosmosDBCopyConnectionString + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openDocument", + async ( + actionContext: IActionContext, + node?: MongoDocumentTreeItem | DocDBDocumentTreeItem + ) => { + if (!node) { + node = await ext.rgApi.pickAppResource< + MongoDocumentTreeItem | DocDBDocumentTreeItem + >(actionContext, { + filter: [cosmosMongoFilter, sqlFilter], + expectedChildContextValue: [ + MongoDocumentTreeItem.contextValue, + DocDBDocumentTreeItem.contextValue, + ], + }); + } + + // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 + ext.fileSystem.fireChangedEvent(node); + await ext.fileSystem.showTextDocument(node); + }, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.update", + async (_actionContext: IActionContext, uri: vscode.Uri) => + await ext.fileSystem.updateWithoutPrompt(uri) + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.loadMore", + async (actionContext: IActionContext, node: AzExtTreeItem) => + await ext.rgApi.appResourceTree.loadMore( + node, + actionContext + ) + ); + registerEvent( + "cosmosDB.onDidChangeConfiguration", + vscode.workspace.onDidChangeConfiguration, + async ( + actionContext: IActionContext, + event: vscode.ConfigurationChangeEvent + ) => { + actionContext.telemetry.properties.isActivationEvent = + "true"; + actionContext.errorHandling.suppressDisplay = true; + if ( + event.affectsConfiguration( + ext.settingsKeys.documentLabelFields + ) + ) { + await vscode.commands.executeCommand( + "azureDatabases.refresh" + ); + } + } + ); + + // Suppress "Report an Issue" button for all errors in favor of the command + registerErrorHandler( + (c) => (c.errorHandling.suppressReportIssue = true) + ); + registerReportIssueCommand("azureDatabases.reportIssue"); + } + ); + + return createApiProvider([ + { + findTreeItem, + pickTreeItem, + revealTreeItem, + apiVersion: "1.2.0", + }, + ]); } // this method is called when your extension is deactivated export function deactivateInternal(): void { - // NOOP + // NOOP } -export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { - if (!node) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); - } +export async function createServer( + context: IActionContext, + node?: SubscriptionTreeItem +): Promise { + if (!node) { + node = + await ext.rgApi.appResourceTree.showTreeItemPicker( + SubscriptionTreeItem.contextValue, + context + ); + } - await SubscriptionTreeItem.createChild(context, node); + await SubscriptionTreeItem.createChild(context, node); } -export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await deleteDatabaseAccount(context, node, false) +export async function deleteAccount( + context: IActionContext, + node?: AzExtTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter, + ], + }); + } + + await deleteDatabaseAccount(context, node, false); } -export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { - const message = 'The connection string has been copied to the clipboard'; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); +export async function cosmosDBCopyConnectionString( + context: IActionContext, + node?: MongoAccountTreeItem | DocDBAccountTreeItemBase +): Promise { + const message = "The connection string has been copied to the clipboard"; + if (!node) { + node = await ext.rgApi.pickAppResource< + MongoAccountTreeItem | DocDBAccountTreeItemBase + >(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter, + ], + }); + } + + await vscode.env.clipboard.writeText(node.connectionString); + void vscode.window.showInformationMessage(message); } diff --git a/Source/extensionVariables.ts b/Source/extensionVariables.ts index 4a3fc2650..3af61432c 100644 --- a/Source/extensionVariables.ts +++ b/Source/extensionVariables.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeDataProvider, + AzExtTreeItem, + IAzExtOutputChannel, +} from "@microsoft/vscode-azext-utils"; import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { ExtensionContext, SecretStorage, TreeView } from "vscode"; import { DatabasesFileSystem } from "./DatabasesFileSystem"; @@ -19,33 +23,34 @@ import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWit * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts */ export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = 'azureDatabases'; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; + export let connectedMongoDB: MongoDatabaseTreeItem | undefined; + export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; + export let context: ExtensionContext; + export let outputChannel: IAzExtOutputChannel; + export let tree: AzExtTreeDataProvider; + export let treeView: TreeView; + export let attachedAccountsNode: AttachedAccountsTreeItem; + export let ignoreBundle: boolean | undefined; + export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; + export let secretStorage: SecretStorage; + export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; + export const prefix: string = "azureDatabases"; + export let fileSystem: DatabasesFileSystem; + export let mongoCodeLensProvider: MongoCodeLensProvider; + export let mongoLanguageClient: MongoDBLanguageClient; + export let rgApi: AzureHostExtensionApi; - export namespace settingsKeys { - export const mongoShellPath = 'mongo.shell.path'; - export const mongoShellArgs = 'mongo.shell.args'; - export const documentLabelFields = 'cosmosDB.documentLabelFields'; - export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; - export const mongoShellTimeout = 'mongo.shell.timeout'; - export const batchSize = 'azureDatabases.batchSize'; + export namespace settingsKeys { + export const mongoShellPath = "mongo.shell.path"; + export const mongoShellArgs = "mongo.shell.args"; + export const documentLabelFields = "cosmosDB.documentLabelFields"; + export const enableEndpointDiscovery = + "cosmosDB.enableEndpointDiscovery"; + export const mongoShellTimeout = "mongo.shell.timeout"; + export const batchSize = "azureDatabases.batchSize"; - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } + export namespace vsCode { + export const proxyStrictSSL = "http.proxyStrictSSL"; + } + } } diff --git a/Source/getExtensionApi.ts b/Source/getExtensionApi.ts index bfd553e74..63efdb7e5 100644 --- a/Source/getExtensionApi.ts +++ b/Source/getExtensionApi.ts @@ -8,24 +8,35 @@ import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { Extension, extensions } from "vscode"; import { localize } from "./utils/localize"; -export async function getApiExport(extensionId: string): Promise { - const extension: Extension | undefined = extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } +export async function getApiExport( + extensionId: string +): Promise { + const extension: Extension | undefined = + extensions.getExtension(extensionId); + if (extension) { + if (!extension.isActive) { + await extension.activate(); + } - return extension.exports; - } + return extension.exports; + } - return undefined; + return undefined; } export async function getResourceGroupsApi(): Promise { - const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); - if (rgApiProvider) { - return rgApiProvider.getApi('0.0.1'); - } else { - throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); - } + const rgApiProvider = + await getApiExport( + "ms-azuretools.vscode-azureresourcegroups" + ); + if (rgApiProvider) { + return rgApiProvider.getApi("0.0.1"); + } else { + throw new Error( + localize( + "noResourceGroupExt", + "Could not find the Azure Resource Groups extension" + ) + ); + } } diff --git a/Source/graph/gremlinEndpoints.ts b/Source/graph/gremlinEndpoints.ts index 1ef6b283d..0bbeae16f 100644 --- a/Source/graph/gremlinEndpoints.ts +++ b/Source/graph/gremlinEndpoints.ts @@ -3,35 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { nonNullValue } from '../utils/nonNull'; -import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { nonNullValue } from "../utils/nonNull"; +import { IGremlinEndpoint } from "../vscode-cosmosdbgraph.api"; -export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; +export async function tryGetGremlinEndpointFromAzure( + client: CosmosDBManagementClient, + resourceGroup: string, + account: string +): Promise { + // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk + const response = await client.databaseAccounts.get(resourceGroup, account); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const endpointUri = response.documentEndpoint; + // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint + return endpointUri ? parseEndpointUrl(endpointUri) : undefined; } -export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ +export function getPossibleGremlinEndpoints( + documentEndpoint: string +): IGremlinEndpoint[] { + // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - const documentSuffix = '.documents.azure.com'; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); + const documentSuffix = ".documents.azure.com"; + if (documentEndpoint.indexOf(documentSuffix) >= 0) { + // Pre-GA style (Dec 2017) + const preGAEndpoint = documentEndpoint.replace( + documentSuffix, + ".graphs.azure.com" + ); - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); + // Post-GA style (Dec 2017) + const postGAEndpoint = documentEndpoint.replace( + documentSuffix, + ".gremlin.cosmosdb.azure.com" + ); - return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } + return [ + parseEndpointUrl(postGAEndpoint), + parseEndpointUrl(preGAEndpoint), + ]; + } else { + console.warn(`Unexpected document URL format: ${documentEndpoint}`); + return [parseEndpointUrl(documentEndpoint)]; + } } /** @@ -39,9 +54,12 @@ export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinE * @param url An account URL such as 'https://.documents.azure.com:443/' */ function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; + const [, protocol, host, , portString] = nonNullValue( + url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), + "urlMatch" + ); + console.assert(!!protocol && !!host, "Unexpected endpoint format"); + const port = parseInt(portString || "443", 10); + console.assert(port > 0, "Unexpected port"); + return { host, port, ssl: protocol.toLowerCase() === "https" }; } diff --git a/Source/graph/registerGraphCommands.ts b/Source/graph/registerGraphCommands.ts index 1746c638b..21e05d9a5 100644 --- a/Source/graph/registerGraphCommands.ts +++ b/Source/graph/registerGraphCommands.ts @@ -3,60 +3,97 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; -import { ext } from '../extensionVariables'; +import { + AzExtTreeItem, + IActionContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; +import { cosmosGremlinFilter, doubleClickDebounceDelay } from "../constants"; +import { ext } from "../extensionVariables"; import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; import { GraphTreeItem } from "./tree/GraphTreeItem"; export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph(context, GraphTreeItem.contextValue); - } - await node.showExplorer(context); - }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createGraphDatabase", + createGraphDatabase + ); + registerCommandWithTreeNodeUnwrapping("cosmosDB.createGraph", createGraph); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteGraphDatabase", + async (context: IActionContext, node?: GraphDatabaseTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph( + context, + GraphDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteGraph", + async (context: IActionContext, node?: GraphCollectionTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph( + context, + GraphCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openGraphExplorer", + async (context: IActionContext, node: GraphTreeItem) => { + if (!node) { + node = await pickGraph( + context, + GraphTreeItem.contextValue + ); + } + await node.showExplorer(context); + }, + doubleClickDebounceDelay + ); } -export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); +export async function createGraphDatabase( + context: IActionContext, + node?: GraphAccountTreeItem +): Promise { + if (!node) { + node = await pickGraph(context); + } + await node.createChild(context); } -export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.createChild(context); +export async function createGraph( + context: IActionContext, + node?: GraphDatabaseTreeItem +): Promise { + if (!node) { + node = await pickGraph( + context, + GraphDatabaseTreeItem.contextValue + ); + } + await node.createChild(context); } -async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosGremlinFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickGraph( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [cosmosGremlinFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/graph/tree/GraphAccountTreeItem.ts b/Source/graph/tree/GraphAccountTreeItem.ts index 7e1f561fa..8025e4f8e 100644 --- a/Source/graph/tree/GraphAccountTreeItem.ts +++ b/Source/graph/tree/GraphAccountTreeItem.ts @@ -3,43 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { DatabaseDefinition, Resource } from "@azure/cosmos"; +import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; +import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; +import { GraphTreeItem } from "./GraphTreeItem"; export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBGraphAccount"; + public contextValue: string = GraphAccountTreeItem.contextValue; - constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + documentEndpoint: string, + private _gremlinEndpoint: IGremlinEndpoint | undefined, + masterKey: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super( + parent, + id, + label, + documentEndpoint, + masterKey, + isEmulator, + databaseAccount + ); + this.valuesToMask.push(documentEndpoint); + if (_gremlinEndpoint) { + this.valuesToMask.push(_gremlinEndpoint.host); + } + } - public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } + public initChild( + database: DatabaseDefinition & Resource + ): GraphDatabaseTreeItem { + return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case GraphDatabaseTreeItem.contextValue: + case GraphCollectionTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case GraphTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/graph/tree/GraphCollectionTreeItem.ts b/Source/graph/tree/GraphCollectionTreeItem.ts index 63709d977..efc25ae4c 100644 --- a/Source/graph/tree/GraphCollectionTreeItem.ts +++ b/Source/graph/tree/GraphCollectionTreeItem.ts @@ -3,85 +3,108 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; +import { + Container, + ContainerDefinition, + CosmosClient, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; +import { IDocDBTreeRoot } from "../../docdb/tree/IDocDBTreeRoot"; +import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; +import { GraphTreeItem } from "./GraphTreeItem"; export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - - } + public static contextValue: string = "cosmosDBGraph"; + public readonly contextValue: string = GraphCollectionTreeItem.contextValue; + public readonly parent: GraphDatabaseTreeItem; + + private readonly _graphTreeItem: GraphTreeItem; + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + private readonly _collection: ContainerDefinition & Resource; + + constructor( + parent: GraphDatabaseTreeItem, + collection: ContainerDefinition & Resource + ) { + super(parent); + this._collection = collection; + this._graphTreeItem = new GraphTreeItem(this, this._collection); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( + this + ); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return this._collection.id; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return [this._graphTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteGraphCollection" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public pickTreeItemImpl( + expectedContextValues: (string | RegExp)[] + ): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case GraphTreeItem.contextValue: + return this._graphTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getDatabaseClient(client).container(this.id); + } } diff --git a/Source/graph/tree/GraphDatabaseTreeItem.ts b/Source/graph/tree/GraphDatabaseTreeItem.ts index 1c5332700..4fc7a9655 100644 --- a/Source/graph/tree/GraphDatabaseTreeItem.ts +++ b/Source/graph/tree/GraphDatabaseTreeItem.ts @@ -3,63 +3,76 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; -import { GraphAccountTreeItem } from './GraphAccountTreeItem'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { + ContainerDefinition, + CosmosClient, + Database, + DatabaseDefinition, + Resource, +} from "@azure/cosmos"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; +import { getPossibleGremlinEndpoints } from "../gremlinEndpoints"; +import { GraphAccountTreeItem } from "./GraphAccountTreeItem"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Graph'; + public static contextValue: string = "cosmosDBGraphDatabase"; + public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Graph"; - constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { - super(parent, database); - } + constructor( + parent: GraphAccountTreeItem, + private _gremlinEndpoint: IGremlinEndpoint | undefined, + database: DatabaseDefinition & Resource + ) { + super(parent, database); + } - public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } + public initChild( + collection: ContainerDefinition & Resource + ): GraphCollectionTreeItem { + return new GraphCollectionTreeItem(this, collection); + } - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } + // Gremlin endpoint, if definitely known + get gremlinEndpoint(): IGremlinEndpoint | undefined { + return this._gremlinEndpoint; + } - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } + get possibleGremlinEndpoints(): IGremlinEndpoint[] { + return getPossibleGremlinEndpoints(this.root.endpoint); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } - } + protected override async getNewPartitionKey( + context: IActionContext + ): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: "Enter the partition key for the collection, or leave blank for fixed size.", + stepName: "partitionKeyForCollection", + validateInput: this.validatePartitionKey, + placeHolder: "e.g. /address", + }); - protected override async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address' - }); + if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { + partitionKey = "/" + partitionKey; + } - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } + return partitionKey; + } - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + if (/.+\//.test(key)) { + return "Cannot be a nested path"; + } + return undefined; + } } diff --git a/Source/graph/tree/GraphTreeItem.ts b/Source/graph/tree/GraphTreeItem.ts index 800fded5a..d98da8b6b 100644 --- a/Source/graph/tree/GraphTreeItem.ts +++ b/Source/graph/tree/GraphTreeItem.ts @@ -3,54 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { ContainerDefinition, Resource } from "@azure/cosmos"; +import { + AzExtTreeItem, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { localize } from "../../utils/localize"; +import { openUrl } from "../../utils/openUrl"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; -const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; +const alternativeGraphVisualizationToolsDocLink = + "https://aka.ms/cosmosdb-graph-alternative-tools"; export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this.commandId = 'cosmosDB.openGraphExplorer'; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } + public static contextValue: string = "cosmosDBGraphGraph"; + public readonly contextValue: string = GraphTreeItem.contextValue; + public readonly parent: GraphCollectionTreeItem; + public suppressMaskLabel = true; + + private readonly _collection: ContainerDefinition & Resource; + + constructor( + parent: GraphCollectionTreeItem, + collection: ContainerDefinition & Resource + ) { + super(parent); + this.commandId = "cosmosDB.openGraphExplorer"; + this._collection = collection; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return "Graph"; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public async showExplorer(_context: IActionContext): Promise { + const message: string = localize( + "mustInstallGraph", + "Cosmos DB Graph extension has been retired." + ); + const alternativeToolsOption = "Alternative Tools"; + const result = await vscode.window.showErrorMessage( + message, + alternativeToolsOption + ); + if (result === alternativeToolsOption) { + await openUrl(alternativeGraphVisualizationToolsDocLink); + } + } } diff --git a/Source/mongo/MongoCommand.ts b/Source/mongo/MongoCommand.ts index 79c33731f..ea9466b45 100644 --- a/Source/mongo/MongoCommand.ts +++ b/Source/mongo/MongoCommand.ts @@ -3,22 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RecognitionException } from 'antlr4ts'; -import * as vscode from 'vscode'; +import { RecognitionException } from "antlr4ts"; +import * as vscode from "vscode"; export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; + range: vscode.Range; + text: string; + collection?: string; + name?: string; + arguments?: string[]; + argumentObjects?: Object[]; + errors?: ErrorDescription[]; + chained?: boolean; } export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; + range: vscode.Range; + message: string; + exception?: RecognitionException; } diff --git a/Source/mongo/MongoScrapbook.ts b/Source/mongo/MongoScrapbook.ts index d5dfe6d00..2f441285e 100644 --- a/Source/mongo/MongoScrapbook.ts +++ b/Source/mongo/MongoScrapbook.ts @@ -3,489 +3,718 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ObjectID } from 'bson'; -import { Collection } from 'mongodb'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { filterType, findType } from '../utils/array'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { mongoLexer } from './grammar/mongoLexer'; -import * as mongoParser from './grammar/mongoParser'; -import { MongoVisitor } from './grammar/visitors'; -import { ErrorDescription, MongoCommand } from './MongoCommand'; -import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; -import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; +import { + IActionContext, + IParsedError, + openReadOnlyContent, + parseError, + ReadOnlyContent, +} from "@microsoft/vscode-azext-utils"; +import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; +import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { ObjectID } from "bson"; +import { Collection } from "mongodb"; +import { EOL } from "os"; +import * as vscode from "vscode"; +import { ext } from "../extensionVariables"; +import { filterType, findType } from "../utils/array"; +import { localize } from "../utils/localize"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { LexerErrorListener, ParserErrorListener } from "./errorListeners"; +import { mongoLexer } from "./grammar/mongoLexer"; +import * as mongoParser from "./grammar/mongoParser"; +import { MongoVisitor } from "./grammar/visitors"; +import { ErrorDescription, MongoCommand } from "./MongoCommand"; +import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; +import { + MongoDatabaseTreeItem, + stripQuotes, +} from "./tree/MongoDatabaseTreeItem"; +import { + IMongoDocument, + MongoDocumentTreeItem, +} from "./tree/MongoDocumentTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); -const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of (command.errors || [])) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; +const notInScrapbookMessage = + "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; + +export function getAllErrorsFromTextDocument( + document: vscode.TextDocument +): vscode.Diagnostic[] { + const commands = getAllCommandsFromTextDocument(document); + const errors: vscode.Diagnostic[] = []; + for (const command of commands) { + for (const error of command.errors || []) { + const diagnostic = new vscode.Diagnostic( + error.range, + error.message + ); + errors.push(diagnostic); + } + } + + return errors; } -export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); +export async function executeAllCommandsFromActiveEditor( + context: IActionContext +): Promise { + ext.outputChannel.appendLog("Executing all commands in scrapbook..."); + const commands = getAllCommandsFromActiveEditor(); + await executeCommands(context, commands); } -export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); - return await executeCommand(context, command); +export async function executeCommandFromActiveEditor( + context: IActionContext, + position?: vscode.Position +): Promise { + const commands = getAllCommandsFromActiveEditor(); + const command = findCommandAtPosition( + commands, + position || vscode.window.activeTextEditor?.selection.start + ); + return await executeCommand(context, command); } function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } + const activeEditor = vscode.window.activeTextEditor; + if (activeEditor) { + return getAllCommandsFromTextDocument(activeEditor.document); + } else { + // Shouldn't be able to reach this + throw new Error(notInScrapbookMessage); + } } -export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { - return getAllCommandsFromText(document.getText()); +export function getAllCommandsFromTextDocument( + document: vscode.TextDocument +): MongoCommand[] { + return getAllCommandsFromText(document.getText()); } -async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { - const label: string = 'Scrapbook-execute-all-results'; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } +async function executeCommands( + context: IActionContext, + commands: MongoCommand[] +): Promise { + const label: string = "Scrapbook-execute-all-results"; + const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; + const readOnlyContent: ReadOnlyContent = await openReadOnlyContent( + { label, fullId }, + "", + ".txt", + { viewColumn: vscode.ViewColumn.Beside } + ); + + for (const command of commands) { + try { + await executeCommand(context, command, readOnlyContent); + } catch (e) { + const err = parseError(e); + if (err.isUserCancelledError) { + throw e; + } else { + const message = `${command.text.split("(")[0]} at ${ + command.range.start.line + 1 + }:${command.range.start.character + 1}: ${err.message}`; + throw new Error(message); + } + } + } } -async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === 'find' && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, 'collection'); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); - await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === 'findOne') { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp(command, 'collection'); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); - if (!colNode) { - throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = 'Scrapbook-results'; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error('No MongoDB command found at the current cursor location.'); - } +async function executeCommand( + context: IActionContext, + command: MongoCommand, + readOnlyContent?: ReadOnlyContent +): Promise { + if (command) { + try { + context.telemetry.properties.command = command.name; + context.telemetry.properties.argsCount = String( + command.arguments ? command.arguments.length : 0 + ); + } catch (error) { + // Ignore + } + + const database = ext.connectedMongoDB; + if (!database) { + throw new Error( + 'Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item' + ); + } + if (command.errors && command.errors.length > 0) { + //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. + const err = command.errors[0]; + throw new Error( + localize( + "unableToParseSyntax", + `Unable to parse syntax. Error near line ${ + err.range.start.line + 1 + }, column ${err.range.start.character + 1}: "${ + err.message + }"` + ) + ); + } + + // we don't handle chained commands so we can only handle "find" if isn't chained + if (command.name === "find" && !command.chained) { + const db = await database.connectToDb(); + const collectionName: string = nonNullProp(command, "collection"); + const collection: Collection = db.collection(collectionName); + // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because + // the executed 'find' command could have a filter or projection that is not handled by a cached tree node + const node = new MongoCollectionTreeItem( + database, + collection, + command.argumentObjects + ); + await ext.fileSystem.showTextDocument(node, { + viewColumn: vscode.ViewColumn.Beside, + }); + } else { + const result = await database.executeCommand(command, context); + if (command.name === "findOne") { + if (result === "null") { + throw new Error(`Could not find any documents`); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const document: IMongoDocument = EJSON.parse(result); + const collectionName: string = nonNullProp( + command, + "collection" + ); + + const collectionId: string = `${database.fullId}/${collectionName}`; + const colNode: MongoCollectionTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + collectionId, + context + ); + if (!colNode) { + throw new Error( + localize( + "failedToFind", + 'Failed to find collection "{0}".', + collectionName + ) + ); + } + const docNode = new MongoDocumentTreeItem(colNode, document); + await ext.fileSystem.showTextDocument(docNode, { + viewColumn: vscode.ViewColumn.Beside, + }); + } else { + if (readOnlyContent) { + await readOnlyContent.append(`${result}${EOL}${EOL}`); + } else { + const label: string = "Scrapbook-results"; + const fullId: string = `${database.fullId}/${label}`; + await openReadOnlyContent( + { label, fullId }, + result, + ".json", + { viewColumn: vscode.ViewColumn.Beside } + ); + } + + await refreshTreeAfterCommand(database, command, context); + } + } + } else { + throw new Error( + "No MongoDB command found at the current cursor location." + ); + } } -async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { - if (command.name === 'drop') { - await database.refresh(context); - } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); - if (collectionNode) { - await collectionNode.refresh(context); - } - } +async function refreshTreeAfterCommand( + database: MongoDatabaseTreeItem, + command: MongoCommand, + context: IActionContext +): Promise { + if (command.name === "drop") { + await database.refresh(context); + } else if ( + command.collection && + command.name && + /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test( + command.name + ) + ) { + const collectionNode = await ext.rgApi.appResourceTree.findTreeItem( + database.fullId + "/" + command.collection, + context + ); + if (collectionNode) { + await collectionNode.refresh(context); + } + } } export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "" - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; + const lexer = new mongoLexer(new InputStream(content)); + const lexerListener = new LexerErrorListener(); + lexer.removeErrorListeners(); // Default listener outputs to the console + lexer.addErrorListener(lexerListener); + const tokens: CommonTokenStream = new CommonTokenStream(lexer); + + const parser = new mongoParser.mongoParser(tokens); + const parserListener = new ParserErrorListener(); + parser.removeErrorListeners(); // Default listener outputs to the console + parser.addErrorListener(parserListener); + + const commandsContext: mongoParser.MongoCommandsContext = + parser.mongoCommands(); + const commands = new FindMongoCommandsVisitor().visit(commandsContext); + + // Match errors with commands based on location + const errors = lexerListener.errors.concat(parserListener.errors); + errors.sort((a, b) => { + const linediff = a.range.start.line - b.range.start.line; + const chardiff = a.range.start.character - b.range.start.character; + return linediff || chardiff; + }); + for (const err of errors) { + const associatedCommand = findCommandAtPosition( + commands, + err.range.start + ); + if (associatedCommand) { + associatedCommand.errors = associatedCommand.errors || []; + associatedCommand.errors.push(err); + } else { + // Create a new command to hook this up to + const emptyCommand: MongoCommand = { + collection: undefined, + name: undefined, + range: err.range, + text: "", + }; + emptyCommand.errors = [err]; + commands.push(emptyCommand); + } + } + + return commands; } -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; +export function findCommandAtPosition( + commands: MongoCommand[], + position?: vscode.Position +): MongoCommand { + let lastCommandOnSameLine: MongoCommand | undefined; + let lastCommandBeforePosition: MongoCommand | undefined; + if (position) { + for (const command of commands) { + if (command.range.contains(position)) { + return command; + } + if (command.range.end.line === position.line) { + lastCommandOnSameLine = command; + } + if (command.range.end.isBefore(position)) { + lastCommandBeforePosition = command; + } + } + } + return ( + lastCommandOnSameLine || + lastCommandBeforePosition || + commands[commands.length - 1] + ); } class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop'); - this.commands.push({ - range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); - return {}; - } - } - - private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' - this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); - if (argumentContextArray.length > 1) { - this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); - return {}; - } - } - - private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { - if (!tokenText) { // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop'); - const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* + private commands: MongoCommand[] = []; + + public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { + const funcCallCount: number = filterType( + ctx.children, + mongoParser.FunctionCallContext + ).length; + const stop = nonNullProp(ctx, "stop"); + this.commands.push({ + range: new vscode.Range( + ctx.start.line - 1, + ctx.start.charPositionInLine, + stop.line - 1, + stop.charPositionInLine + ), + text: ctx.text, + name: "", + arguments: [], + argumentObjects: [], + chained: funcCallCount > 1 ? true : false, + }); + return super.visitCommand(ctx); + } + + public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { + this.commands[this.commands.length - 1].collection = ctx.text; + return super.visitCollection(ctx); + } + + public visitFunctionCall( + ctx: mongoParser.FunctionCallContext + ): MongoCommand[] { + if (ctx.parent instanceof mongoParser.CommandContext) { + this.commands[this.commands.length - 1].name = + (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; + } + return super.visitFunctionCall(ctx); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { + try { + const argumentsContext = ctx.parent; + if (argumentsContext) { + const functionCallContext = argumentsContext.parent; + if ( + functionCallContext && + functionCallContext.parent instanceof + mongoParser.CommandContext + ) { + const lastCommand = this.commands[this.commands.length - 1]; + const argAsObject = this.contextToObject(ctx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const argText = EJSON.stringify(argAsObject); + nonNullProp(lastCommand, "arguments").push(argText); + const escapeHandled = + this.deduplicateEscapesForRegex(argText); + let ejsonParsed = {}; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + ejsonParsed = EJSON.parse(escapeHandled); + } catch (error) { + //EJSON parse failed due to a wrong flag, etc. + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + nonNullProp(lastCommand, "argumentObjects").push( + ejsonParsed + ); + } + } + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + return super.visitArgument(ctx); + } + + protected defaultResult(_node: ParseTree): MongoCommand[] { + return this.commands; + } + + private contextToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + if (!ctx || ctx.childCount === 0) { + //Base case and malformed statements + return {}; + } + // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 + const child: ParseTree = nonNullProp(ctx, "children")[0]; + if (child instanceof mongoParser.LiteralContext) { + return this.literalContextToObject(child, ctx); + } else if (child instanceof mongoParser.ObjectLiteralContext) { + return this.objectLiteralContextToObject(child); + } else if (child instanceof mongoParser.ArrayLiteralContext) { + return this.arrayLiteralContextToObject(child); + } else if (child instanceof mongoParser.FunctionCallContext) { + return this.functionCallContextToObject(child, ctx); + } else if (child instanceof ErrorNode) { + return {}; + } else { + this.addErrorToCommand( + `Unrecognized node type encountered. We could not parse ${child.text}`, + ctx + ); + return {}; + } + } + + private literalContextToObject( + child: mongoParser.LiteralContext, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + const text = child.text; + const tokenType = child.start.type; + const nonStringLiterals = [ + mongoParser.mongoParser.NullLiteral, + mongoParser.mongoParser.BooleanLiteral, + mongoParser.mongoParser.NumericLiteral, + ]; + if (tokenType === mongoParser.mongoParser.StringLiteral) { + return stripQuotes(text); + } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { + return this.regexLiteralContextToObject(ctx, text); + } else if (nonStringLiterals.indexOf(tokenType) > -1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return JSON.parse(text); + } else { + this.addErrorToCommand( + `Unrecognized token. Token text: ${text}`, + ctx + ); + return {}; + } + } + + private objectLiteralContextToObject( + child: mongoParser.ObjectLiteralContext + ): Object { + const propertyNameAndValue = findType( + child.children, + mongoParser.PropertyNameAndValueListContext + ); + if (!propertyNameAndValue) { + // Argument is {} + return {}; + } else { + const parsedObject: Object = {}; + const propertyAssignments = filterType( + propertyNameAndValue.children, + mongoParser.PropertyAssignmentContext + ); + for (const propertyAssignment of propertyAssignments) { + const propertyAssignmentChildren = nonNullProp( + propertyAssignment, + "children" + ); + const propertyName = ( + propertyAssignmentChildren[0] + ); + const propertyValue = ( + propertyAssignmentChildren[2] + ); + parsedObject[stripQuotes(propertyName.text)] = + this.contextToObject(propertyValue); + } + return parsedObject; + } + } + + private arrayLiteralContextToObject( + child: mongoParser.ArrayLiteralContext + ) { + const elementList = findType( + child.children, + mongoParser.ElementListContext + ); + if (elementList) { + const elementItems = filterType( + elementList.children, + mongoParser.PropertyValueContext + ); + return elementItems.map(this.contextToObject.bind(this)); + } else { + return []; + } + } + + private functionCallContextToObject( + child: mongoParser.FunctionCallContext, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + const functionTokens = child.children; + const constructorCall: TerminalNode = nonNullValue( + findType(functionTokens, TerminalNode), + "constructorCall" + ); + const argumentsToken: mongoParser.ArgumentsContext = nonNullValue( + findType(functionTokens, mongoParser.ArgumentsContext), + "argumentsToken" + ); + if ( + !( + argumentsToken._CLOSED_PARENTHESIS && + argumentsToken._OPEN_PARENTHESIS + ) + ) { + //argumentsToken does not have '(' or ')' + this.addErrorToCommand( + `Expecting parentheses or quotes at '${constructorCall.text}'`, + ctx + ); + return {}; + } + + const argumentContextArray: mongoParser.ArgumentContext[] = filterType( + argumentsToken.children, + mongoParser.ArgumentContext + ); + if (argumentContextArray.length > 1) { + this.addErrorToCommand( + `Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, + ctx + ); + return {}; + } + + const tokenText: string | undefined = argumentContextArray.length + ? argumentContextArray[0].text + : undefined; + switch (constructorCall.text) { + case "ObjectId": + return this.objectIdToObject(ctx, tokenText); + case "ISODate": + return this.isodateToObject(ctx, tokenText); + case "Date": + return this.dateToObject(ctx, tokenText); + default: + this.addErrorToCommand( + `Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, + ctx + ); + return {}; + } + } + + private dateToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText); + if (date instanceof Date) { + return { $date: date.toString() }; + } else { + return date; + } + } + + private isodateToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); + + if (date instanceof Date) { + return { $date: date.toISOString() }; + } else { + return date; + } + } + + private tryToConstructDate( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string, + isIsodate: boolean = false + ): Date | {} { + if (!tokenText) { + // usage : ObjectID() + return new Date(); + } else { + try { + tokenText = stripQuotes(tokenText); + + // if the tokenText was an isodate, the last char must be Z + if (isIsodate) { + if (tokenText[tokenText.length - 1] !== "Z") { + tokenText += "Z"; + } + } + + return new Date(tokenText); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + } + + private objectIdToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): Object { + let hexID: string; + let constructedObject: ObjectID; + if (!tokenText) { + // usage : ObjectID() + constructedObject = new ObjectID(); + } else { + hexID = stripQuotes(tokenText); + try { + constructedObject = new ObjectID(hexID); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + return { $oid: constructedObject.toString() }; + } + + private regexLiteralContextToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + text: string + ): Object { + const separator = text.lastIndexOf("/"); + const flags = + separator !== text.length - 1 ? text.substring(separator + 1) : ""; + const pattern = text.substring(1, separator); + try { + // validate the pattern and flags. + // It is intended for the errors thrown here to be handled by the catch block. + let tokenObject = new RegExp(pattern, flags); + // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars + tokenObject = tokenObject; + // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax + return { + $regex: this.regexToStringNotation(pattern), + $options: flags, + }; + } catch (error) { + //User may not have finished typing + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + + private addErrorToCommand( + errorMessage: string, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): void { + const command = this.commands[this.commands.length - 1]; + command.errors = command.errors || []; + const stop = nonNullProp(ctx, "stop"); + const currentErrorDesc: ErrorDescription = { + message: errorMessage, + range: new vscode.Range( + ctx.start.line - 1, + ctx.start.charPositionInLine, + stop.line - 1, + stop.charPositionInLine + ), + }; + command.errors.push(currentErrorDesc); + } + + private regexToStringNotation(pattern: string): string { + // The equivalence: + // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" + return pattern.replace(/\\([0-9a-z.*])/i, "\\\\$1"); + } + + private deduplicateEscapesForRegex(argAsString: string): string { + const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; + /* We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } - + return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); + } } diff --git a/Source/mongo/MongoShell.ts b/Source/mongo/MongoShell.ts index b8f982ee8..81784f2af 100644 --- a/Source/mongo/MongoShell.ts +++ b/Source/mongo/MongoShell.ts @@ -3,185 +3,216 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; -import { randomUtils } from '../utils/randomUtils'; -import { getBatchSizeSetting } from '../utils/workspacUtils'; -import { wrapError } from '../utils/wrapError'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as os from "os"; +import * as vscode from "vscode"; +import { InteractiveChildProcess } from "../utils/InteractiveChildProcess"; +import { randomUtils } from "../utils/randomUtils"; +import { getBatchSizeSetting } from "../utils/workspacUtils"; +import { wrapError } from "../utils/wrapError"; -const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; +const timeoutMessage = + "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = '(More)'; +const extensionMoreMessage = "(More)"; -const sentinelBase = 'EXECUTION COMPLETED'; +const sentinelBase = "EXECUTION COMPLETED"; const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } +function createSentinel(): string { + return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; +} export class MongoShell extends vscode.Disposable { - - constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { - super(() => this.dispose()); - } - - public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '' - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut(text => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); - - resolve(stdOutNoSentinel); - } - })); - disposables.push( - this._process.onStdErr(text => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - })); - disposables.push( - this._process.onError(error => { - reject(error); - })); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error("The process exited prematurely."); - } - - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } - finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } + constructor( + private _process: InteractiveChildProcess, + private _timeoutSeconds: number + ) { + super(() => this.dispose()); + } + + public static async create( + execPath: string, + execArgs: string[], + connectionString: string, + isEmulator: boolean | undefined, + outputChannel: vscode.OutputChannel, + timeoutSeconds: number + ): Promise { + try { + const args: string[] = execArgs.slice() || []; // Snapshot since we modify it + args.push(connectionString); + + if (isEmulator) { + // Without these the connection will fail due to the self-signed DocDB certificate + if (args.indexOf("--ssl") < 0) { + args.push("--ssl"); + } + if (args.indexOf("--sslAllowInvalidCertificates") < 0) { + args.push("--sslAllowInvalidCertificates"); + } + } + + const process: InteractiveChildProcess = + await InteractiveChildProcess.create({ + outputChannel: outputChannel, + command: execPath, + args, + outputFilterSearch: sentinelRegex, + outputFilterReplace: "", + }); + const shell: MongoShell = new MongoShell(process, timeoutSeconds); + + // Try writing an empty script to verify the process is running correctly and allow us + // to catch any errors related to the start-up of the process before trying to write to it. + await shell.executeScript(""); + + // Configure the batch size + await shell.executeScript( + `DBQuery.shellBatchSize = ${getBatchSizeSetting()}` + ); + + return shell; + } catch (error) { + throw wrapCheckOutputWindow(error); + } + } + + public dispose(): void { + this._process.kill(); + } + + public async useDatabase(database: string): Promise { + return await this.executeScript(`use ${database}`); + } + + public async executeScript(script: string): Promise { + script = convertToSingleLine(script); + + let stdOut = ""; + const sentinel = createSentinel(); + + const disposables: vscode.Disposable[] = []; + try { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + const result = await new Promise( + async (resolve, reject) => { + try { + startScriptTimeout(this._timeoutSeconds, reject); + + // Hook up events + disposables.push( + this._process.onStdOut((text) => { + stdOut += text; + // eslint-disable-next-line prefer-const + let { text: stdOutNoSentinel, removed } = + removeSentinel(stdOut, sentinel); + if (removed) { + // The sentinel was found, which means we are done. + + // Change the "type 'it' for more" message to one that doesn't ask users to type anything, + // since we're not currently interactive like that. + // CONSIDER: Ideally we would allow users to click a button to iterate through more data, + // or even just do it for them + stdOutNoSentinel = stdOutNoSentinel.replace( + mongoShellMoreMessage, + extensionMoreMessage + ); + + resolve(stdOutNoSentinel); + } + }) + ); + disposables.push( + this._process.onStdErr((text) => { + // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. + // So consider this an error. + // (It's okay if we fire this multiple times, the first one wins.) + reject(wrapCheckOutputWindow(text.trim())); + }) + ); + disposables.push( + this._process.onError((error) => { + reject(error); + }) + ); + + // Write the script to STDIN + if (script) { + this._process.writeLine(script); + } + + // Mark end of result by sending the sentinel wrapped in quotes so the console will spit + // it back out as a string value after it's done processing the script + const quotedSentinel = `"${sentinel}"`; + this._process.writeLine(quotedSentinel); // (Don't display the sentinel) + } catch (error) { + // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it + + if ((<{ code?: string }>error).code === "EPIPE") { + // Give a chance for start-up errors to show up before rejecting with this more general error message + await delay(500); + // eslint-disable-next-line no-ex-assign + error = new Error( + "The process exited prematurely." + ); + } + + reject(wrapCheckOutputWindow(error)); + } + } + ); + + return result.trim(); + } finally { + // Dispose event handlers + for (const d of disposables) { + d.dispose(); + } + } + } } -function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout( - () => { - reject(timeoutMessage); - }, - timeoutSeconds * 1000); - } +function startScriptTimeout( + timeoutSeconds: number | 0, + reject: (err: unknown) => void +): void { + if (timeoutSeconds > 0) { + setTimeout(() => { + reject(timeoutMessage); + }, timeoutSeconds * 1000); + } } function convertToSingleLine(script: string): string { - return script.split(os.EOL) - .map(line => line.trim()) - .join(''); - + return script + .split(os.EOL) + .map((line) => line.trim()) + .join(""); } -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } +function removeSentinel( + text: string, + sentinel: string +): { text: string; removed: boolean } { + const index = text.indexOf(sentinel); + if (index >= 0) { + return { text: text.slice(0, index), removed: true }; + } else { + return { text, removed: false }; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); + const checkOutputMsg = + "The output window may contain additional information."; + return parseError(error).message.includes(checkOutputMsg) + ? error + : wrapError(error, checkOutputMsg); } diff --git a/Source/mongo/connectToMongoClient.ts b/Source/mongo/connectToMongoClient.ts index 88aa2df17..e2fe8d5d1 100644 --- a/Source/mongo/connectToMongoClient.ts +++ b/Source/mongo/connectToMongoClient.ts @@ -3,47 +3,58 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MongoClient, MongoClientOptions } from 'mongodb'; -import { emulatorPassword, Links } from '../constants'; - -export async function connectToMongoClient(connectionString: string, appName: string): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string, name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - throw error; - } +import { MongoClient, MongoClientOptions } from "mongodb"; +import { emulatorPassword, Links } from "../constants"; + +export async function connectToMongoClient( + connectionString: string, + appName: string +): Promise { + // appname appears to be the correct equivalent to user-agent for mongo + const options: MongoClientOptions = { + // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string + appName: `@${appName}@`, + // https://github.com/lmammino/mongo-uri-builder/issues/2 + useNewUrlParser: true, + useUnifiedTopology: true, + }; + + if (isCosmosEmulatorConnectionString(connectionString)) { + // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 + options.tlsAllowInvalidCertificates = true; + } + + try { + return await MongoClient.connect(connectionString, options); + } catch (err) { + // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info + const error = <{ message?: string; name?: string }>err; + const message = error && error.message; + + // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" + // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" + if ( + message && + /ECONNREFUSED/.test(message) && + /(localhost|127\.0\.0\.1)/.test(message) + ) { + throw new MongoConnectError(); + } + + throw error; + } } export class MongoConnectError extends Error { - constructor() { - super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); - } + constructor() { + super( + `Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.` + ); + } } -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); +export function isCosmosEmulatorConnectionString( + connectionString: string +): boolean { + return connectionString.includes(encodeURIComponent(emulatorPassword)); } diff --git a/Source/mongo/errorListeners.ts b/Source/mongo/errorListeners.ts index ea582d544..00d510cd5 100644 --- a/Source/mongo/errorListeners.ts +++ b/Source/mongo/errorListeners.ts @@ -3,65 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { Recognizer } from 'antlr4ts/Recognizer'; -import { Token } from 'antlr4ts/Token'; +import { ANTLRErrorListener } from "antlr4ts/ANTLRErrorListener"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { Recognizer } from "antlr4ts/Recognizer"; +import { Token } from "antlr4ts/Token"; import * as vscode from "vscode"; -import { ErrorDescription } from './MongoCommand'; +import { ErrorDescription } from "./MongoCommand"; export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; - public get errors(): ErrorDescription[] { - return this._errors; - } + public get errors(): ErrorDescription[] { + return this._errors; + } - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: Token | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e, + }; + this._errors.push(error); + } } export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } + private _errors: ErrorDescription[] = []; - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { + public get errors(): ErrorDescription[] { + return this._errors; + } - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: number | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e, + }; + this._errors.push(error); + } } diff --git a/Source/mongo/grammar/mongoLexer.ts b/Source/mongo/grammar/mongoLexer.ts index 3b6cbbdd0..47b461a6f 100644 --- a/Source/mongo/grammar/mongoLexer.ts +++ b/Source/mongo/grammar/mongoLexer.ts @@ -9,239 +9,312 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { RuleContext } from 'antlr4ts/RuleContext'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; +import { CharStream } from "antlr4ts/CharStream"; +import { NotNull, Override } from "antlr4ts/Decorators"; +import { Lexer } from "antlr4ts/Lexer"; +import * as Utils from "antlr4ts/misc/Utils"; +import { RuleContext } from "antlr4ts/RuleContext"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +export class mongoLexer extends Lexer { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly modeNames: string[] = ["DEFAULT_MODE"]; + public static readonly ruleNames: string[] = [ + "T__0", + "T__1", + "T__2", + "T__3", + "T__4", + "T__5", + "T__6", + "T__7", + "RegexLiteral", + "RegexFlag", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "STRING_ESCAPE", + "DecimalIntegerLiteral", + "ExponentPart", + "DecimalDigit", + "WHITESPACE", + ]; -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = [ - "DEFAULT_MODE" - ]; - - public static readonly ruleNames: string[] = [ - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", - "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", - "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", - "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", - "ExponentPart", "DecimalDigit", "WHITESPACE" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoLexer.ruleNames; } - - @Override - public get serializedATN(): string { return mongoLexer._serializedATN; } - - @Override - public get modeNames(): string[] { return mongoLexer.modeNames; } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text) - ; - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, + "'('", + "','", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "':'", + undefined, + undefined, + undefined, + undefined, + "'null'", + undefined, + undefined, + undefined, + undefined, + "';'", + "'.'", + "'db'", + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + "RegexLiteral", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "WHITESPACE", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( + mongoLexer._LITERAL_NAMES, + mongoLexer._SYMBOLIC_NAMES, + [] + ); -} + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoLexer.VOCABULARY; + } + + private isExternalIdentifierText(text) { + return text === "db"; + } + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(mongoLexer._ATN, this); + } + + @Override + public get grammarFileName(): string { + return "mongo.g4"; + } + @Override + public get ruleNames(): string[] { + return mongoLexer.ruleNames; + } + + @Override + public get serializedATN(): string { + return mongoLexer._serializedATN; + } + + @Override + public get modeNames(): string[] { + return mongoLexer.modeNames; + } + + @Override + public sempred( + _localctx: RuleContext, + ruleIndex: number, + predIndex: number + ): boolean { + switch (ruleIndex) { + case 21: + return this.IDENTIFIER_sempred(_localctx, predIndex); + } + return true; + } + private IDENTIFIER_sempred( + _localctx: RuleContext, + predIndex: number + ): boolean { + switch (predIndex) { + case 0: + return !this.isExternalIdentifierText(this.text); + } + return true; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + + "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + + "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + + "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + + "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + + "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + + "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + + "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + + "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + + "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + + "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + + "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + + "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + + "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + + "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + + "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + + "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + + "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + + "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + + "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + + "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + + "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + + "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + + "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + + "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + + "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" + + "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + + "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + + 'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' + + "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + + 'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' + + "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + + "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + + "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + + "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + + "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + + "\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + + "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + + ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + + "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + + "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + + "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + + "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + + "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" + + "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + + "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + + "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + + "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + + "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + + "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + + "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + + "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + + "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + + "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + + "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + + "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + + "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + + "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + + "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + + "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + + "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + + "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + + "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + + "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + + "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + + "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + + "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + + "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + + "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + + "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + + "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + + "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + + '\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' + + "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + + "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + + "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + + "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + + "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + + "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + + "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + + "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + + "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + + "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + + "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + + "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + + "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + + "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + + "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + + "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + + "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + + "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + + "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + + "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + + "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + + "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + + "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + + "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + + "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + + "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + + "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + + "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + + "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + + "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + + "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + + "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + + "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + + "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + + "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + + "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + + "\x04\x02\x03\x02\b\x02\x02"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoLexer.__ATN) { + mongoLexer.__ATN = new ATNDeserializer().deserialize( + Utils.toCharArray(mongoLexer._serializedATN) + ); + } + + return mongoLexer.__ATN; + } +} diff --git a/Source/mongo/grammar/mongoListener.ts b/Source/mongo/grammar/mongoListener.ts index 43514f500..d1d8ffac8 100644 --- a/Source/mongo/grammar/mongoListener.ts +++ b/Source/mongo/grammar/mongoListener.ts @@ -1,17 +1,30 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - - -import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { + ArgumentContext, + ArgumentsContext, + ArrayLiteralContext, + CollectionContext, + CommandContext, + CommandsContext, + CommentContext, + ElementListContext, + EmptyCommandContext, + FunctionCallContext, + LiteralContext, + MongoCommandsContext, + ObjectLiteralContext, + PropertyAssignmentContext, + PropertyNameAndValueListContext, + PropertyNameContext, + PropertyValueContext, +} from "./mongoParser"; /** * This interface defines a complete listener for a parse tree produced by @@ -143,12 +156,16 @@ export interface mongoListener extends ParseTreeListener { * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; + enterPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => void; /** * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; + exitPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => void; /** * Enter a parse tree produced by `mongoParser.propertyAssignment`. @@ -205,4 +222,3 @@ export interface mongoListener extends ParseTreeListener { */ exitComment?: (ctx: CommentContext) => void; } - diff --git a/Source/mongo/grammar/mongoParser.ts b/Source/mongo/grammar/mongoParser.ts index c1d38f4d0..f08e3ff51 100644 --- a/Source/mongo/grammar/mongoParser.ts +++ b/Source/mongo/grammar/mongoParser.ts @@ -9,1458 +9,1650 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { TokenStream } from 'antlr4ts/TokenStream'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { mongoListener } from './mongoListener'; -import { mongoVisitor } from './mongoVisitor'; - - - +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; +import { NotNull, Override } from "antlr4ts/Decorators"; +import * as Utils from "antlr4ts/misc/Utils"; +import { NoViableAltException } from "antlr4ts/NoViableAltException"; +import { Parser } from "antlr4ts/Parser"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { RuleVersion } from "antlr4ts/RuleVersion"; +import { Token } from "antlr4ts/Token"; +import { TokenStream } from "antlr4ts/TokenStream"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +import { mongoListener } from "./mongoListener"; +import { mongoVisitor } from "./mongoVisitor"; export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", "commands", "command", "emptyCommand", "collection", - "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", - "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", - "literal", "propertyName", "comment" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoParser.ruleNames; } - - @Override - public get serializedATN(): string { return mongoParser._serializedATN; } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + - "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } - + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly RULE_mongoCommands = 0; + public static readonly RULE_commands = 1; + public static readonly RULE_command = 2; + public static readonly RULE_emptyCommand = 3; + public static readonly RULE_collection = 4; + public static readonly RULE_functionCall = 5; + public static readonly RULE_arguments = 6; + public static readonly RULE_argument = 7; + public static readonly RULE_objectLiteral = 8; + public static readonly RULE_arrayLiteral = 9; + public static readonly RULE_elementList = 10; + public static readonly RULE_propertyNameAndValueList = 11; + public static readonly RULE_propertyAssignment = 12; + public static readonly RULE_propertyValue = 13; + public static readonly RULE_literal = 14; + public static readonly RULE_propertyName = 15; + public static readonly RULE_comment = 16; + public static readonly ruleNames: string[] = [ + "mongoCommands", + "commands", + "command", + "emptyCommand", + "collection", + "functionCall", + "arguments", + "argument", + "objectLiteral", + "arrayLiteral", + "elementList", + "propertyNameAndValueList", + "propertyAssignment", + "propertyValue", + "literal", + "propertyName", + "comment", + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, + "'('", + "','", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "':'", + undefined, + undefined, + undefined, + undefined, + "'null'", + undefined, + undefined, + undefined, + undefined, + "';'", + "'.'", + "'db'", + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + "RegexLiteral", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "WHITESPACE", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( + mongoParser._LITERAL_NAMES, + mongoParser._SYMBOLIC_NAMES, + [] + ); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoParser.VOCABULARY; + } + + @Override + public get grammarFileName(): string { + return "mongo.g4"; + } + + @Override + public get ruleNames(): string[] { + return mongoParser.ruleNames; + } + + @Override + public get serializedATN(): string { + return mongoParser._serializedATN; + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(mongoParser._ATN, this); + } + @RuleVersion(0) + public mongoCommands(): MongoCommandsContext { + const _localctx: MongoCommandsContext = new MongoCommandsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 34; + this.commands(); + this.state = 35; + this.match(mongoParser.EOF); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public commands(): CommandsContext { + const _localctx: CommandsContext = new CommandsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 2, mongoParser.RULE_commands); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 42; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.SingleLineComment) | + (1 << mongoParser.MultiLineComment) | + (1 << mongoParser.SEMICOLON) | + (1 << mongoParser.DB))) !== + 0 + ) { + { + this.state = 40; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.DB: + { + this.state = 37; + this.command(); + } + break; + case mongoParser.SEMICOLON: + { + this.state = 38; + this.emptyCommand(); + } + break; + case mongoParser.SingleLineComment: + case mongoParser.MultiLineComment: + { + this.state = 39; + this.comment(); + } + break; + default: + throw new NoViableAltException(this); + } + } + this.state = 44; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public command(): CommandContext { + const _localctx: CommandContext = new CommandContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 4, mongoParser.RULE_command); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 45; + this.match(mongoParser.DB); + this.state = 48; + this._errHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this._input, 2, this._ctx) + ) { + case 1: + { + this.state = 46; + this.match(mongoParser.DOT); + this.state = 47; + this.collection(); + } + break; + } + this.state = 52; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 50; + this.match(mongoParser.DOT); + this.state = 51; + this.functionCall(); + } + } + this.state = 54; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la === mongoParser.DOT); + this.state = 57; + this._errHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this._input, 4, this._ctx) + ) { + case 1: + { + this.state = 56; + this.match(mongoParser.SEMICOLON); + } + break; + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public emptyCommand(): EmptyCommandContext { + const _localctx: EmptyCommandContext = new EmptyCommandContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 59; + this.match(mongoParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public collection(): CollectionContext { + const _localctx: CollectionContext = new CollectionContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 8, mongoParser.RULE_collection); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 61; + this.match(mongoParser.IDENTIFIER); + this.state = 66; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 5, + this._ctx + ); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 62; + this.match(mongoParser.DOT); + this.state = 63; + this.match(mongoParser.IDENTIFIER); + } + } + } + this.state = 68; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 5, + this._ctx + ); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public functionCall(): FunctionCallContext { + const _localctx: FunctionCallContext = new FunctionCallContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 69; + _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); + this.state = 70; + this.arguments(); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arguments(): ArgumentsContext { + const _localctx: ArgumentsContext = new ArgumentsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 12, mongoParser.RULE_arguments); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 72; + _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); + this.state = 81; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.T__3) | + (1 << mongoParser.T__5) | + (1 << mongoParser.RegexLiteral) | + (1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral) | + (1 << mongoParser.NumericLiteral))) !== + 0 + ) { + { + this.state = 73; + this.argument(); + this.state = 78; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 74; + this.match(mongoParser.T__1); + this.state = 75; + this.argument(); + } + } + this.state = 80; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + this.state = 83; + _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public argument(): ArgumentContext { + const _localctx: ArgumentContext = new ArgumentContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 14, mongoParser.RULE_argument); + try { + this.state = 88; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 85; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 86; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 87; + this.arrayLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public objectLiteral(): ObjectLiteralContext { + const _localctx: ObjectLiteralContext = new ObjectLiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 90; + this.match(mongoParser.T__3); + this.state = 92; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + _la === mongoParser.StringLiteral || + _la === mongoParser.IDENTIFIER + ) { + { + this.state = 91; + this.propertyNameAndValueList(); + } + } + + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.T__1) { + { + this.state = 94; + this.match(mongoParser.T__1); + } + } + + this.state = 97; + this.match(mongoParser.T__4); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arrayLiteral(): ArrayLiteralContext { + const _localctx: ArrayLiteralContext = new ArrayLiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 99; + this.match(mongoParser.T__5); + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.T__3) | + (1 << mongoParser.T__5) | + (1 << mongoParser.RegexLiteral) | + (1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral) | + (1 << mongoParser.NumericLiteral) | + (1 << mongoParser.IDENTIFIER))) !== + 0 + ) { + { + this.state = 100; + this.elementList(); + } + } + + this.state = 103; + this.match(mongoParser.T__6); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public elementList(): ElementListContext { + const _localctx: ElementListContext = new ElementListContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 20, mongoParser.RULE_elementList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 105; + this.propertyValue(); + this.state = 110; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 106; + this.match(mongoParser.T__1); + this.state = 107; + this.propertyValue(); + } + } + this.state = 112; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyNameAndValueList(): PropertyNameAndValueListContext { + const _localctx: PropertyNameAndValueListContext = + new PropertyNameAndValueListContext(this._ctx, this.state); + this.enterRule( + _localctx, + 22, + mongoParser.RULE_propertyNameAndValueList + ); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 113; + this.propertyAssignment(); + this.state = 118; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 13, + this._ctx + ); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 114; + this.match(mongoParser.T__1); + this.state = 115; + this.propertyAssignment(); + } + } + } + this.state = 120; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 13, + this._ctx + ); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyAssignment(): PropertyAssignmentContext { + const _localctx: PropertyAssignmentContext = + new PropertyAssignmentContext(this._ctx, this.state); + this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 121; + this.propertyName(); + this.state = 122; + this.match(mongoParser.T__7); + this.state = 123; + this.propertyValue(); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyValue(): PropertyValueContext { + const _localctx: PropertyValueContext = new PropertyValueContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); + try { + this.state = 129; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 125; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 126; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 127; + this.arrayLiteral(); + } + break; + case mongoParser.IDENTIFIER: + this.enterOuterAlt(_localctx, 4); + { + this.state = 128; + this.functionCall(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public literal(): LiteralContext { + const _localctx: LiteralContext = new LiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 28, mongoParser.RULE_literal); + let _la: number; + try { + this.state = 134; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 131; + _la = this._input.LA(1); + if ( + !( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral))) !== + 0 + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + break; + case mongoParser.RegexLiteral: + this.enterOuterAlt(_localctx, 2); + { + this.state = 132; + this.match(mongoParser.RegexLiteral); + } + break; + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 3); + { + this.state = 133; + this.match(mongoParser.NumericLiteral); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyName(): PropertyNameContext { + const _localctx: PropertyNameContext = new PropertyNameContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 136; + _la = this._input.LA(1); + if ( + !( + _la === mongoParser.StringLiteral || + _la === mongoParser.IDENTIFIER + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public comment(): CommentContext { + const _localctx: CommentContext = new CommentContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 32, mongoParser.RULE_comment); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 138; + _la = this._input.LA(1); + if ( + !( + _la === mongoParser.SingleLineComment || + _la === mongoParser.MultiLineComment + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + + "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + + "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + + "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + + "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + + "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + + "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + + "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + + "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + + "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + + "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + + '\x1C\x02\x1E\x02 \x02"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17' + + "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + + "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + + "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + + "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + + "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + + '\x02\x02"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03' + + "\x03\x02\x02\x02'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*'" + + "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + + ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + + "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + + "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + + "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + + "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + + "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + + "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + + "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + + "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + + "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + + "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + + "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + + "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + + "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + + "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + + "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + + "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + + "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + + "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + + "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + + "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + + "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + + "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + + "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + + "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + + "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + + "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + + "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + + "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + + "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + + "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + + "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoParser.__ATN) { + mongoParser.__ATN = new ATNDeserializer().deserialize( + Utils.toCharArray(mongoParser._serializedATN) + ); + } + + return mongoParser.__ATN; + } } export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } + public commands(): CommandsContext { + return this.getRuleContext(0, CommandsContext); + } + public EOF(): TerminalNode { + return this.getToken(mongoParser.EOF, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_mongoCommands; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterMongoCommands) listener.enterMongoCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitMongoCommands) listener.exitMongoCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); + else return visitor.visitChildren(this); + } } - export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } + public command(): CommandContext[]; + public command(i: number): CommandContext; + public command(i?: number): CommandContext | CommandContext[] { + if (i === undefined) { + return this.getRuleContexts(CommandContext); + } else { + return this.getRuleContext(i, CommandContext); + } + } + public emptyCommand(): EmptyCommandContext[]; + public emptyCommand(i: number): EmptyCommandContext; + public emptyCommand( + i?: number + ): EmptyCommandContext | EmptyCommandContext[] { + if (i === undefined) { + return this.getRuleContexts(EmptyCommandContext); + } else { + return this.getRuleContext(i, EmptyCommandContext); + } + } + public comment(): CommentContext[]; + public comment(i: number): CommentContext; + public comment(i?: number): CommentContext | CommentContext[] { + if (i === undefined) { + return this.getRuleContexts(CommentContext); + } else { + return this.getRuleContext(i, CommentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_commands; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommands) listener.enterCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommands) listener.exitCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommands) return visitor.visitCommands(this); + else return visitor.visitChildren(this); + } } - export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_command; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } + public DB(): TerminalNode { + return this.getToken(mongoParser.DB, 0); + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + public collection(): CollectionContext | undefined { + return this.tryGetRuleContext(0, CollectionContext); + } + public functionCall(): FunctionCallContext[]; + public functionCall(i: number): FunctionCallContext; + public functionCall( + i?: number + ): FunctionCallContext | FunctionCallContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionCallContext); + } else { + return this.getRuleContext(i, FunctionCallContext); + } + } + public SEMICOLON(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.SEMICOLON, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_command; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommand) listener.enterCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommand) listener.exitCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommand) return visitor.visitCommand(this); + else return visitor.visitChildren(this); + } } - export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } + public SEMICOLON(): TerminalNode { + return this.getToken(mongoParser.SEMICOLON, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_emptyCommand; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); + else return visitor.visitChildren(this); + } } - export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.IDENTIFIER); + } else { + return this.getToken(mongoParser.IDENTIFIER, i); + } + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_collection; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCollection) listener.enterCollection(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCollection) listener.exitCollection(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCollection) return visitor.visitCollection(this); + else return visitor.visitChildren(this); + } } - export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } + public _FUNCTION_NAME: Token; + public arguments(): ArgumentsContext { + return this.getRuleContext(0, ArgumentsContext); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(mongoParser.IDENTIFIER, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_functionCall; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterFunctionCall) listener.enterFunctionCall(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitFunctionCall) listener.exitFunctionCall(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); + else return visitor.visitChildren(this); + } } - export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } + public _OPEN_PARENTHESIS: Token; + public _CLOSED_PARENTHESIS: Token; + public argument(): ArgumentContext[]; + public argument(i: number): ArgumentContext; + public argument(i?: number): ArgumentContext | ArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(ArgumentContext); + } else { + return this.getRuleContext(i, ArgumentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_arguments; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArguments) listener.enterArguments(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArguments) listener.exitArguments(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArguments) return visitor.visitArguments(this); + else return visitor.visitChildren(this); + } } - export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_argument; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArgument) listener.enterArgument(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArgument) listener.exitArgument(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArgument) return visitor.visitArgument(this); + else return visitor.visitChildren(this); + } } - export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } + public propertyNameAndValueList(): + | PropertyNameAndValueListContext + | undefined { + return this.tryGetRuleContext(0, PropertyNameAndValueListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_objectLiteral; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); + else return visitor.visitChildren(this); + } } - export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } + public elementList(): ElementListContext | undefined { + return this.tryGetRuleContext(0, ElementListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_arrayLiteral; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); + else return visitor.visitChildren(this); + } } - export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } + public propertyValue(): PropertyValueContext[]; + public propertyValue(i: number): PropertyValueContext; + public propertyValue( + i?: number + ): PropertyValueContext | PropertyValueContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyValueContext); + } else { + return this.getRuleContext(i, PropertyValueContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_elementList; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterElementList) listener.enterElementList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitElementList) listener.exitElementList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitElementList) return visitor.visitElementList(this); + else return visitor.visitChildren(this); + } } - export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } + public propertyAssignment(): PropertyAssignmentContext[]; + public propertyAssignment(i: number): PropertyAssignmentContext; + public propertyAssignment( + i?: number + ): PropertyAssignmentContext | PropertyAssignmentContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyAssignmentContext); + } else { + return this.getRuleContext(i, PropertyAssignmentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyNameAndValueList; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyNameAndValueList) + listener.enterPropertyNameAndValueList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyNameAndValueList) + listener.exitPropertyNameAndValueList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyNameAndValueList) + return visitor.visitPropertyNameAndValueList(this); + else return visitor.visitChildren(this); + } } - export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } + public propertyName(): PropertyNameContext { + return this.getRuleContext(0, PropertyNameContext); + } + public propertyValue(): PropertyValueContext { + return this.getRuleContext(0, PropertyValueContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyAssignment; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyAssignment) + listener.enterPropertyAssignment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyAssignment) + listener.exitPropertyAssignment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyAssignment) + return visitor.visitPropertyAssignment(this); + else return visitor.visitChildren(this); + } } - export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + public functionCall(): FunctionCallContext | undefined { + return this.tryGetRuleContext(0, FunctionCallContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyValue; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyValue) listener.enterPropertyValue(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyValue) listener.exitPropertyValue(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); + else return visitor.visitChildren(this); + } } - export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } - public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } - public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } + public NullLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.NullLiteral, 0); + } + public BooleanLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.BooleanLiteral, 0); + } + public StringLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.StringLiteral, 0); + } + public RegexLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.RegexLiteral, 0); + } + public NumericLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.NumericLiteral, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_literal; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterLiteral) listener.enterLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitLiteral) listener.exitLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitLiteral) return visitor.visitLiteral(this); + else return visitor.visitChildren(this); + } } - export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } + public StringLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.StringLiteral, 0); + } + public IDENTIFIER(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.IDENTIFIER, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyName; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyName) listener.enterPropertyName(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyName) listener.exitPropertyName(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyName) return visitor.visitPropertyName(this); + else return visitor.visitChildren(this); + } } - export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } - public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } + public SingleLineComment(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.SingleLineComment, 0); + } + public MultiLineComment(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.MultiLineComment, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_comment; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterComment) listener.enterComment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitComment) listener.exitComment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitComment) return visitor.visitComment(this); + else return visitor.visitChildren(this); + } } - - diff --git a/Source/mongo/grammar/mongoVisitor.ts b/Source/mongo/grammar/mongoVisitor.ts index eb001a6e9..105184d2d 100644 --- a/Source/mongo/grammar/mongoVisitor.ts +++ b/Source/mongo/grammar/mongoVisitor.ts @@ -1,17 +1,30 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - - -import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - +import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; +import { + ArgumentContext, + ArgumentsContext, + ArrayLiteralContext, + CollectionContext, + CommandContext, + CommandsContext, + CommentContext, + ElementListContext, + EmptyCommandContext, + FunctionCallContext, + LiteralContext, + MongoCommandsContext, + ObjectLiteralContext, + PropertyAssignmentContext, + PropertyNameAndValueListContext, + PropertyNameContext, + PropertyValueContext, +} from "./mongoParser"; /** * This interface defines a complete generic visitor for a parse tree produced @@ -103,7 +116,9 @@ export interface mongoVisitor extends ParseTreeVisitor { * @param ctx the parse tree * @return the visitor result */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; + visitPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => Result; /** * Visit a parse tree produced by `mongoParser.propertyAssignment`. @@ -140,4 +155,3 @@ export interface mongoVisitor extends ParseTreeVisitor { */ visitComment?: (ctx: CommentContext) => Result; } - diff --git a/Source/mongo/grammar/visitors.ts b/Source/mongo/grammar/visitors.ts index e1ba1b63d..20e69315d 100644 --- a/Source/mongo/grammar/visitors.ts +++ b/Source/mongo/grammar/visitors.ts @@ -3,81 +3,88 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; -import { mongoVisitor } from './mongoVisitor'; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { + ArgumentContext, + ArgumentsContext, + CollectionContext, + CommandContext, + CommandsContext, + FunctionCallContext, + MongoCommandsContext, +} from "./mongoParser"; +import { mongoVisitor } from "./mongoVisitor"; export class MongoVisitor implements mongoVisitor { - - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return null; - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } + visitMongoCommands(ctx: MongoCommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommands(ctx: CommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommand(ctx: CommandContext): T { + return this.visitChildren(ctx); + } + + visitCollection(ctx: CollectionContext): T { + return this.visitChildren(ctx); + } + + visitFunctionCall(ctx: FunctionCallContext): T { + return this.visitChildren(ctx); + } + + visitArgument(ctx: ArgumentContext): T { + return this.visitChildren(ctx); + } + + visitArguments(ctx: ArgumentsContext): T { + return this.visitChildren(ctx); + } + + visit(tree: ParseTree): T { + return tree.accept(this); + } + + visitChildren(ctx: ParserRuleContext): T { + let result = this.defaultResult(ctx); + const n = ctx.childCount; + for (let i = 0; i < n; i++) { + if (!this.shouldVisitNextChild(ctx, result)) { + break; + } + + const childNode = ctx.getChild(i); + const childResult = childNode.accept(this); + result = this.aggregateResult(result, childResult); + } + return result; + } + + visitTerminal(node: TerminalNode): T { + return this.defaultResult(node); + } + + visitErrorNode(node: ErrorNode): T { + return this.defaultResult(node); + } + + protected defaultResult(_node: ParseTree): T { + // grandfathered-in. Unclear why this is null instead of type T + return (null); + } + + protected aggregateResult(aggregate: T, nextResult: T): T { + return !nextResult ? aggregate : nextResult; + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + shouldVisitNextChild(_node, _currentResult: T): boolean { + return true; + } } diff --git a/Source/mongo/languageClient.ts b/Source/mongo/languageClient.ts index e4bd4aefd..6f445423e 100644 --- a/Source/mongo/languageClient.ts +++ b/Source/mongo/languageClient.ts @@ -2,57 +2,81 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -import * as nls from 'vscode-nls'; -import { ext } from '../extensionVariables'; -import { IConnectionParams } from './services/IConnectionParams'; +import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; +import * as path from "path"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from "vscode-languageclient"; +import * as nls from "vscode-nls"; +import { ext } from "../extensionVariables"; +import { IConnectionParams } from "./services/IConnectionParams"; const localize = nls.loadMessageBundle(); export class MongoDBLanguageClient { + public client: LanguageClient; - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle ? - ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : - ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'mongo', scheme: 'file' }, - { language: 'mongo', scheme: 'untitled' } - ] - }; - - // Create the language client and start the client. - this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect(connectionString: string, databaseName: string): Promise { - await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } + constructor() { + // The server is implemented in node + const serverModule = ext.ignoreBundle + ? ext.context.asAbsolutePath( + path.join("out", "src", "mongo", "languageServer.js") + ) + : ext.context.asAbsolutePath( + path.join("dist", "mongo-languageServer.bundle.js") + ); + // The debug options for the server + const debugOptions = { execArgv: ["--nolazy", "--inspect=6005"] }; + + // If the extension is launch in debug mode the debug server options are use + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + options: debugOptions, + }, + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for mongo javascript documents + documentSelector: [ + { language: "mongo", scheme: "file" }, + { language: "mongo", scheme: "untitled" }, + ], + }; + + // Create the language client and start the client. + this.client = new LanguageClient( + "mongo", + localize("mongo.server.name", "Mongo Language Server"), + serverOptions, + clientOptions + ); + const disposable = this.client.start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + ext.context.subscriptions.push(disposable); + } + + public async connect( + connectionString: string, + databaseName: string + ): Promise { + await this.client.sendRequest("connect", { + connectionString: connectionString, + databaseName: databaseName, + extensionUserAgent: appendExtensionUserAgent(), + }); + } + + public async disconnect(): Promise { + await this.client.sendRequest("disconnect"); + } } diff --git a/Source/mongo/languageServer.ts b/Source/mongo/languageServer.ts index d5d6ec484..8c76686f6 100644 --- a/Source/mongo/languageServer.ts +++ b/Source/mongo/languageServer.ts @@ -2,8 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from 'vscode-languageserver'; -import { LanguageService } from './services/languageService'; +import { createConnection, IConnection } from "vscode-languageserver"; +import { LanguageService } from "./services/languageService"; // // diff --git a/Source/mongo/mongoConnectionStrings.ts b/Source/mongo/mongoConnectionStrings.ts index 5f73db484..89d04ed30 100644 --- a/Source/mongo/mongoConnectionStrings.ts +++ b/Source/mongo/mongoConnectionStrings.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; +import { + appendExtensionUserAgent, + IParsedError, + parseError, +} from "@microsoft/vscode-azext-utils"; import { MongoClient } from "mongodb"; import { testDb } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; @@ -21,84 +25,118 @@ import { connectToMongoClient } from "./connectToMongoClient"; // mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] // [database] -const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; -const parseDatabaseName = '\/?([^/?]+)?'; +const parsePrefix = "([a-zA-Z]+://[^/]*)"; +const parseDatabaseName = "/?([^/?]+)?"; const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } +export function getDatabaseNameFromConnectionString( + connectionString: string +): string | undefined { + try { + const [, , databaseName] = nonNullValue( + connectionString.match(mongoConnectionStringRegExp), + "databaseNameMatch" + ); + return databaseName; + } catch (error) { + // Shouldn't happen, but ignore if does + } - return undefined; + return undefined; } -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } +export function addDatabaseToAccountConnectionString( + connectionString: string, + databaseName: string +): string { + try { + return connectionString.replace( + mongoConnectionStringRegExp, + `$1\/${encodeURIComponent(databaseName)}` + ); + } catch (error) { + // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it + return connectionString; + } } -export async function parseMongoConnectionString(connectionString: string): Promise { +export async function parseMongoConnectionString( + connectionString: string +): Promise { + let mongoClient: MongoClient; + try { + mongoClient = await connectToMongoClient( + connectionString, + appendExtensionUserAgent() + ); + } catch (error) { + const parsedError: IParsedError = parseError(error); + if (parsedError.message.match(/unescaped/i)) { + // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 + connectionString = encodeMongoConnectionString(connectionString); + mongoClient = await connectToMongoClient( + connectionString, + appendExtensionUserAgent() + ); + } else { + throw error; + } + } - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const serverConfig: any = mongoClient.db(testDb).serverConfig; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; + // get the first connection string from the servers list + // this may not be best solution, but the connection (below) gives + // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) + // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const host: string = + serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const port: string = + serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - - return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); + return new ParsedMongoConnectionString( + connectionString, + host, + port, + getDatabaseNameFromConnectionString(connectionString) + ); } export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } + constructor( + connectionString: string, + hostName: string, + port: string, + databaseName: string | undefined + ) { + super(connectionString, databaseName); + this.hostName = hostName; + this.port = port; + } } /** * Encodes the username and password in the given Mongo DB connection string. */ export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } + const matches: RegExpMatchArray | null = connectionString.match( + /^(.*):\/\/(.*):(.*)@(.*)/ + ); + if (matches) { + const prefix: string = matches[1]; + const username: string = matches[2]; + const password: string = matches[3]; + const hostAndQuery: string = matches[4]; + connectionString = `${prefix}://${encodeURIComponent( + username + )}:${encodeURIComponent(password)}@${hostAndQuery}`; + } - return connectionString; + return connectionString; } diff --git a/Source/mongo/registerMongoCommands.ts b/Source/mongo/registerMongoCommands.ts index 2dc36477a..713ff9104 100644 --- a/Source/mongo/registerMongoCommands.ts +++ b/Source/mongo/registerMongoCommands.ts @@ -3,15 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { Experience, MongoExperience } from '../AzureDBExperiences'; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, + IErrorHandlerContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, + registerErrorHandler, + registerEvent, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { Experience, MongoExperience } from "../AzureDBExperiences"; import { cosmosMongoFilter } from "../constants"; import { ext } from "../extensionVariables"; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { MongoConnectError } from './connectToMongoClient'; +import * as vscodeUtil from "../utils/vscodeUtils"; +import { MongoConnectError } from "./connectToMongoClient"; import { MongoDBLanguageClient } from "./languageClient"; -import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; +import { + executeAllCommandsFromActiveEditor, + executeCommandFromActiveEditor, + getAllErrorsFromTextDocument, +} from "./MongoScrapbook"; import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; import { setConnectedNode } from "./setConnectedNode"; import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; @@ -19,205 +32,328 @@ import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; -const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; +const connectedMongoKey: string = "ms-azuretools.vscode-cosmosdb.connectedDB"; let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = 'mongo'; +const mongoLanguageId: string = "mongo"; export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); - } - - const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); - if (oldNode) { - await oldNode.refresh(context); - } - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); - registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - }); + ext.mongoLanguageClient = new MongoDBLanguageClient(); + + ext.mongoCodeLensProvider = new MongoCodeLensProvider(); + ext.context.subscriptions.push( + vscode.languages.registerCodeLensProvider( + mongoLanguageId, + ext.mongoCodeLensProvider + ) + ); + + diagnosticsCollection = + vscode.languages.createDiagnosticCollection("cosmosDB.mongo"); + ext.context.subscriptions.push(diagnosticsCollection); + + setUpErrorReporting(); + + const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); + + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoDatabase", + createMongoDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoCollection", + createMongoCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoDocument", + async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + const documentNode = await node.createChild(context); + await vscode.commands.executeCommand( + "cosmosDB.openDocument", + documentNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.connectMongoDB", + async (context: IActionContext, node?: MongoDatabaseTreeItem) => { + if (!node) { + // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 + const experienceContext: ITreeItemPickerContext & { + defaultExperience?: Experience; + } = { ...context, defaultExperience: MongoExperience }; + node = await pickMongo( + experienceContext, + MongoDatabaseTreeItem.contextValue + ); + } + + const oldNodeId: string | undefined = + ext.connectedMongoDB && ext.connectedMongoDB.fullId; + await ext.mongoLanguageClient.connect( + node.connectionString, + node.databaseName + ); + void ext.context.globalState.update(connectedMongoKey, node.fullId); + setConnectedNode(node); + await node.refresh(context); + + if (oldNodeId) { + // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldNode: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + oldNodeId, + context + ); + if (oldNode) { + await oldNode.refresh(context); + } + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoDB", + deleteMongoDB + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoCollection", + deleteMongoCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoDocument", + async (context: IActionContext, node?: MongoDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoDocumentTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openCollection", + async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + await ext.fileSystem.showTextDocument(node); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.launchMongoShell", + launchMongoShell + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.newMongoScrapbook", + async () => await vscodeUtil.showNewFile("", "Scrapbook", ".mongo") + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.executeMongoCommand", + async (context: IActionContext, position?: vscode.Position) => { + await loadPersistedMongoDBTask; + await executeCommandFromActiveEditor(context, position); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.executeAllMongoCommands", + async (context: IActionContext) => { + await loadPersistedMongoDBTask; + await executeAllCommandsFromActiveEditor(context); + } + ); } async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling( + "cosmosDB.loadPersistedMongoDB", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = "true"; + + try { + const persistedNodeId: string | undefined = + ext.context.globalState.get(connectedMongoKey); + if (persistedNodeId) { + const persistedNode = + await ext.rgApi.appResourceTree.findTreeItem( + persistedNodeId, + context + ); + if (persistedNode) { + await ext.mongoLanguageClient.client.onReady(); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + persistedNode + ); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedMongoDB) { + ext.mongoCodeLensProvider.setConnectedDatabase(undefined); + } + } + } + ); } function launchMongoShell(): void { - const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); - terminal.sendText(`mongo`); - terminal.show(); + const terminal: vscode.Terminal = + vscode.window.createTerminal("Mongo Shell"); + terminal.sendText(`mongo`); + terminal.show(); } function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }); - - // Update errors when document opened/changed - registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); + // Update errors immediately in case a scrapbook is already open + void callWithTelemetryAndErrorHandling( + "initialUpdateErrorsInActiveDocument", + async (context: IActionContext) => { + updateErrorsInScrapbook( + context, + vscode.window.activeTextEditor?.document + ); + } + ); + + // Update errors when document opened/changed + registerEvent( + "vscode.workspace.onDidOpenTextDocument", + vscode.workspace.onDidOpenTextDocument, + updateErrorsInScrapbook + ); + registerEvent( + "vscode.workspace.onDidChangeTextDocument", + vscode.workspace.onDidChangeTextDocument, + async ( + context: IActionContext, + event: vscode.TextDocumentChangeEvent + ) => { + // Always suppress success telemetry - event happens on every keystroke + context.telemetry.suppressIfSuccessful = true; + + updateErrorsInScrapbook(context, event.document); + } + ); + registerEvent( + "vscode.workspace.onDidCloseTextDocument", + vscode.workspace.onDidCloseTextDocument, + async (context: IActionContext, document: vscode.TextDocument) => { + // Remove errors when closed + if (document?.languageId === mongoLanguageId) { + diagnosticsCollection.set(document.uri, []); + } else { + context.telemetry.suppressIfSuccessful = true; + } + } + ); + + registerErrorHandler((context: IErrorHandlerContext) => { + if (context.error instanceof MongoConnectError) { + context.errorHandling.suppressReportIssue = true; + } + }); } -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } +function updateErrorsInScrapbook( + context: IActionContext, + document: vscode.TextDocument | undefined +): void { + if (document?.languageId === mongoLanguageId) { + const errors = getAllErrorsFromTextDocument(document); + diagnosticsCollection.set(document.uri, errors); + } else { + context.telemetry.suppressIfSuccessful = true; + } } -export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); +export async function createMongoDatabase( + context: IActionContext, + node?: MongoAccountTreeItem +): Promise { + if (!node) { + node = await pickMongo(context); + } + const databaseNode = await node.createChild(context); + await databaseNode.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + databaseNode + ); } -export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); +export async function createMongoCollection( + context: IActionContext, + node?: MongoDatabaseTreeItem +): Promise { + if (!node) { + node = await pickMongo( + context, + MongoDatabaseTreeItem.contextValue + ); + } + const collectionNode = await node.createChild(context); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + collectionNode.parent + ); } -export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } +export async function deleteMongoDB( + context: IActionContext, + node?: MongoDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { + setConnectedNode(undefined); + void ext.context.globalState.update(connectedMongoKey, undefined); + // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 + void ext.mongoLanguageClient.disconnect(); + } } -export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteMongoCollection( + context: IActionContext, + node?: MongoCollectionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickMongo( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [cosmosMongoFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/mongo/services/IConnectionParams.ts b/Source/mongo/services/IConnectionParams.ts index eec39e4cf..55d2cc73a 100644 --- a/Source/mongo/services/IConnectionParams.ts +++ b/Source/mongo/services/IConnectionParams.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; + connectionString: string; + databaseName: string; + extensionUserAgent: string; } diff --git a/Source/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts index 3407c50dd..01aaff56f 100644 --- a/Source/mongo/services/MongoCodeLensProvider.ts +++ b/Source/mongo/services/MongoCodeLensProvider.ts @@ -3,73 +3,89 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: vscode.EventEmitter = + new vscode.EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): vscode.Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses( + document: vscode.TextDocument, + _token: vscode.CancellationToken + ): vscode.ProviderResult { + return callWithTelemetryAndErrorHandling( + "mongo.provideCodeLenses", + (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: vscode.CodeLens[] = []; - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized ? - 'Initializing...' : - isConnected ? - `Connected to ${database}` : - `Connect to a database`, - command: isInitialized && 'cosmosDB.connectMongoDB' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title: !isInitialized + ? "Initializing..." + : isConnected + ? `Connected to ${database}` + : `Connect to a database`, + command: isInitialized && "cosmosDB.connectMongoDB", + }, + range: new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(0, 0) + ), + }); - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: 'cosmosDB.executeAllMongoCommands' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); + if (isConnected) { + // Run all + lenses.push({ + command: { + title: "Execute All", + command: "cosmosDB.executeAllMongoCommands", + }, + range: new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(0, 0) + ), + }); - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: 'cosmosDB.executeMongoCommand', - arguments: [cmd.range.start] - }, - range: cmd.range - }); - } - } + const commands = getAllCommandsFromTextDocument(document); + for (const cmd of commands) { + // run individual + lenses.push({ + command: { + title: "Execute", + command: "cosmosDB.executeMongoCommand", + arguments: [cmd.range.start], + }, + range: cmd.range, + }); + } + } - return lenses; - }); - } + return lenses; + } + ); + } } diff --git a/Source/mongo/services/completionItemProvider.ts b/Source/mongo/services/completionItemProvider.ts index cba51890c..4abb71432 100644 --- a/Source/mongo/services/completionItemProvider.ts +++ b/Source/mongo/services/completionItemProvider.ts @@ -5,435 +5,588 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) - .then(list => { - return list!.items.map(item => { - const startPositionOffset = document.offsetAt(item.textEdit!.range.start); - const endPositionOffset = document.offsetAt(item.textEdit!.range.end); - item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range - }, - kind: CompletionItemKind.Keyword, - label: 'db' - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range) - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then(collections => { - return collections.map(collection => ({ - textEdit: { - newText: collection.collectionName, - range - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}` - })); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range) - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}` - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } - +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Db } from "mongodb"; +import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; +import { + CompletionItem, + CompletionItemKind, + Position, + Range, +} from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { mongoLexer } from "./../grammar/mongoLexer"; +import * as mongoParser from "./../grammar/mongoParser"; +import { MongoVisitor } from "./../grammar/visitors"; +import { SchemaService } from "./schemaService"; + +export class CompletionItemsVisitor extends MongoVisitor< + Promise +> { + private at: Position; + + constructor( + private textDocument: TextDocument, + private db: Db, + private offset: number, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + super(); + this.at = this.textDocument.positionAt(this.offset); + } + + public visitCommands( + ctx: mongoParser.CommandsContext + ): Promise { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(ctx)) + ); + } + + public visitEmptyCommand( + ctx: mongoParser.EmptyCommandContext + ): Promise { + return this.thenable( + this.createDbKeywordCompletion(this.createRangeAfter(ctx)) + ); + } + + public visitCommand( + ctx: mongoParser.CommandContext + ): Promise { + if (ctx.childCount === 0) { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(ctx)) + ); + } + + const lastTerminalNode = this.getLastTerminalNode(ctx); + if (lastTerminalNode) { + return this.getCompletionItemsFromTerminalNode(lastTerminalNode); + } + return this.thenable(); + } + + public visitCollection( + ctx: mongoParser.CollectionContext + ): Promise { + return Promise.all([ + this.createCollectionCompletions(this.createRange(ctx)), + this.createDbFunctionCompletions(this.createRange(ctx)), + ]).then(([collectionCompletions, dbFunctionCompletions]) => [ + ...collectionCompletions, + ...dbFunctionCompletions, + ]); + } + + public visitFunctionCall( + ctx: mongoParser.FunctionCallContext + ): Promise { + const previousNode = this.getPreviousNode(ctx); + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return this.thenable(); + } + + public visitArguments( + ctx: mongoParser.ArgumentsContext + ): Promise { + const terminalNode = this.getLastTerminalNode(ctx); + if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { + return this.thenable( + this.createDbKeywordCompletion( + this.createRangeAfter(terminalNode) + ) + ); + } + return this.thenable(); + } + + public visitArgument( + ctx: mongoParser.ArgumentContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitObjectLiteral( + ctx: mongoParser.ObjectLiteralContext + ): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if ( + [ + "find", + "findOne", + "findOneAndDelete", + "findOneAndUpdate", + "findOneAndReplace", + "deleteOne", + "deleteMany", + "remove", + ].indexOf(functionName) !== -1 + ) { + return this.getArgumentCompletionItems( + this.schemaService.queryDocumentUri(collectionName), + collectionName, + ctx + ); + } + } + return ctx.parent!.accept(this); + } + + public visitArrayLiteral( + ctx: mongoParser.ArrayLiteralContext + ): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (["aggregate"].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems( + this.schemaService.aggregateDocumentUri(collectionName), + collectionName, + ctx + ); + } + } + return ctx.parent!.accept(this); + } + + public visitElementList( + ctx: mongoParser.ElementListContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyNameAndValueList( + ctx: mongoParser.PropertyNameAndValueListContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyAssignment( + ctx: mongoParser.PropertyAssignmentContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyValue( + ctx: mongoParser.PropertyValueContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyName( + ctx: mongoParser.PropertyNameContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitLiteral( + ctx: mongoParser.LiteralContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitTerminal(ctx: TerminalNode): Promise { + return ctx.parent!.accept(this); + } + + public visitErrorNode(ctx: ErrorNode): Promise { + return ctx.parent!.accept(this); + } + + private getArgumentCompletionItems( + documentUri: string, + _collectionName: string, + ctx: ParserRuleContext + ): Thenable { + const text = this.textDocument.getText(); + const document = TextDocument.create( + documentUri, + "json", + 1, + text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1) + ); + const positionOffset = this.textDocument.offsetAt(this.at); + const contextOffset = ctx.start.startIndex; + const position = document.positionAt(positionOffset - contextOffset); + return this.jsonLanguageService + .doComplete( + document, + position, + this.jsonLanguageService.parseJSONDocument(document) + ) + .then((list) => { + return list!.items.map((item) => { + const startPositionOffset = document.offsetAt( + item.textEdit!.range.start + ); + const endPositionOffset = document.offsetAt( + item.textEdit!.range.end + ); + item.textEdit!.range = Range.create( + this.textDocument.positionAt( + startPositionOffset + contextOffset + ), + this.textDocument.positionAt( + contextOffset + endPositionOffset + ) + ); + return item; + }); + }); + } + + private getFunctionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + return (parent)._FUNCTION_NAME.text!; + } + + private getCollectionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + let previousNode = this.getPreviousNode(parent); + if ( + previousNode && + previousNode instanceof TerminalNode && + previousNode.symbol.type === mongoLexer.DOT + ) { + previousNode = this.getPreviousNode(previousNode); + if ( + previousNode && + previousNode instanceof mongoParser.CollectionContext + ) { + return previousNode.text; + } + } + return null!; + } + + private getCompletionItemsFromTerminalNode( + node: TerminalNode + ): Promise { + if (node._symbol.type === mongoParser.mongoParser.DB) { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(node)) + ); + } + if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { + return this.thenable( + this.createDbKeywordCompletion(this.createRangeAfter(node)) + ); + } + if (node._symbol.type === mongoParser.mongoParser.DOT) { + const previousNode = this.getPreviousNode(node); + if (previousNode && previousNode instanceof TerminalNode) { + if (previousNode._symbol.type === mongoParser.mongoParser.DB) { + return Promise.all([ + this.createCollectionCompletions( + this.createRangeAfter(node) + ), + this.createDbFunctionCompletions( + this.createRangeAfter(node) + ), + ]).then( + ([collectionCompletions, dbFunctionCompletions]) => [ + ...collectionCompletions, + ...dbFunctionCompletions, + ] + ); + } + } + if (previousNode instanceof mongoParser.CollectionContext) { + return this.createCollectionFunctionsCompletions( + this.createRangeAfter(node) + ); + } + } + if (node instanceof ErrorNode) { + const previousNode = this.getPreviousNode(node); + if (previousNode) { + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode( + previousNode + ); + } + return previousNode.accept(this); + } + } + return this.thenable(); + } + + private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { + return ctx.children ? ctx.children + .slice() + .reverse() + .filter( + (node) => + node instanceof TerminalNode && + node.symbol.stopIndex > -1 && + node.symbol.stopIndex < this.offset + )[0] : null!; + } + + private getPreviousNode(node: ParseTree): ParseTree { + let previousNode: ParseTree = null!; + const parentNode = node.parent!; + for (let i = 0; i < parentNode.childCount; i++) { + const currentNode = parentNode.getChild(i); + if (currentNode === node) { + break; + } + previousNode = currentNode; + } + return previousNode; + } + + private createDbKeywordCompletion(range: Range): CompletionItem { + return { + textEdit: { + newText: "db", + range, + }, + kind: CompletionItemKind.Keyword, + label: "db", + }; + } + + private createDbFunctionCompletions( + range: Range + ): Promise { + return this.thenable( + this.createFunctionCompletion("adminCommand", range), + this.createFunctionCompletion("auth", range), + this.createFunctionCompletion("cloneDatabase", range), + this.createFunctionCompletion("commandHelp", range), + this.createFunctionCompletion("copyDatabase", range), + this.createFunctionCompletion("createCollection", range), + this.createFunctionCompletion("createView", range), + this.createFunctionCompletion("createUser", range), + this.createFunctionCompletion("currentOp", range), + this.createFunctionCompletion("dropDatabase", range), + this.createFunctionCompletion("eval", range), + this.createFunctionCompletion("fsyncLock", range), + this.createFunctionCompletion("fsyncUnLock", range), + this.createFunctionCompletion("getCollection", range), + this.createFunctionCompletion("getCollectionInfos", range), + this.createFunctionCompletion("getCollectionNames", range), + this.createFunctionCompletion("getLastError", range), + this.createFunctionCompletion("getLastErrorObj", range), + this.createFunctionCompletion("getLogComponents", range), + this.createFunctionCompletion("getMongo", range), + this.createFunctionCompletion("getName", range), + this.createFunctionCompletion("getPrevError", range), + this.createFunctionCompletion("getProfilingLevel", range), + this.createFunctionCompletion("getProfilingStatus", range), + this.createFunctionCompletion("getReplicationInfo", range), + this.createFunctionCompletion("getSiblingDB", range), + this.createFunctionCompletion("getWriteConcern", range), + this.createFunctionCompletion("hostInfo", range), + this.createFunctionCompletion("isMaster", range), + this.createFunctionCompletion("killOp", range), + this.createFunctionCompletion("listCommands", range), + this.createFunctionCompletion("loadServerScripts", range), + this.createFunctionCompletion("logout", range), + this.createFunctionCompletion("printCollectionStats", range), + this.createFunctionCompletion("printReplicationInfo", range), + this.createFunctionCompletion("printShardingStatus", range), + this.createFunctionCompletion("printSlaveReplicationInfo", range), + this.createFunctionCompletion("dropUser", range), + this.createFunctionCompletion("repairDatabase", range), + this.createFunctionCompletion("runCommand", range), + this.createFunctionCompletion("serverStatus", range), + this.createFunctionCompletion("setLogLevel", range), + this.createFunctionCompletion("setProfilingLevel", range), + this.createFunctionCompletion("setWriteConcern", range), + this.createFunctionCompletion("unsetWriteConcern", range), + this.createFunctionCompletion("setVerboseShell", range), + this.createFunctionCompletion("shotdownServer", range), + this.createFunctionCompletion("stats", range), + this.createFunctionCompletion("version", range) + ); + } + + private createCollectionCompletions( + range: Range + ): Promise { + if (this.db) { + return >( + this.db.collections().then((collections) => { + return collections.map( + (collection) => + { + textEdit: { + newText: collection.collectionName, + range, + }, + label: collection.collectionName, + kind: CompletionItemKind.Property, + filterText: collection.collectionName, + sortText: `1:${collection.collectionName}`, + } + ); + }) + ); + } + return Promise.resolve([]); + } + + private createCollectionFunctionsCompletions( + range: Range + ): Promise { + return this.thenable( + this.createFunctionCompletion("bulkWrite", range), + this.createFunctionCompletion("count", range), + this.createFunctionCompletion("copyTo", range), + this.createFunctionCompletion("convertToCapped", range), + this.createFunctionCompletion("createIndex", range), + this.createFunctionCompletion("createIndexes", range), + this.createFunctionCompletion("dataSize", range), + this.createFunctionCompletion("deleteOne", range), + this.createFunctionCompletion("deleteMany", range), + this.createFunctionCompletion("distinct", range), + this.createFunctionCompletion("drop", range), + this.createFunctionCompletion("dropIndex", range), + this.createFunctionCompletion("dropIndexes", range), + this.createFunctionCompletion("ensureIndex", range), + this.createFunctionCompletion("explain", range), + this.createFunctionCompletion("reIndex", range), + this.createFunctionCompletion("find", range), + this.createFunctionCompletion("findOne", range), + this.createFunctionCompletion("findOneAndDelete", range), + this.createFunctionCompletion("findOneAndReplace", range), + this.createFunctionCompletion("findOneAndUpdate", range), + this.createFunctionCompletion("getDB", range), + this.createFunctionCompletion("getPlanCache", range), + this.createFunctionCompletion("getIndexes", range), + this.createFunctionCompletion("group", range), + this.createFunctionCompletion("insert", range), + this.createFunctionCompletion("insertOne", range), + this.createFunctionCompletion("insertMany", range), + this.createFunctionCompletion("mapReduce", range), + this.createFunctionCompletion("aggregate", range), + this.createFunctionCompletion("remove", range), + this.createFunctionCompletion("replaceOne", range), + this.createFunctionCompletion("renameCollection", range), + this.createFunctionCompletion("runCommand", range), + this.createFunctionCompletion("save", range), + this.createFunctionCompletion("stats", range), + this.createFunctionCompletion("storageSize", range), + this.createFunctionCompletion("totalIndexSize", range), + this.createFunctionCompletion("update", range), + this.createFunctionCompletion("updateOne", range), + this.createFunctionCompletion("updateMany", range), + this.createFunctionCompletion("validate", range), + this.createFunctionCompletion("getShardVersion", range), + this.createFunctionCompletion("getShardDistribution", range), + this.createFunctionCompletion("getSplitKeysForChunks", range), + this.createFunctionCompletion("getWriteConcern", range), + this.createFunctionCompletion("setWriteConcern", range), + this.createFunctionCompletion("unsetWriteConcern", range), + this.createFunctionCompletion("latencyStats", range) + ); + } + + private createFunctionCompletion( + label: string, + range: Range + ): CompletionItem { + return { + textEdit: { + newText: label, + range, + }, + kind: CompletionItemKind.Function, + label, + sortText: `2:${label}`, + }; + } + + private createRange(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + const startToken = parserRuleContext.start; + let stopToken = parserRuleContext.stop; + if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { + stopToken = startToken; + } + + const stop = stopToken.stopIndex; + return this._createRange(startToken.startIndex, stop); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange( + parserRuleContext.symbol.startIndex, + parserRuleContext.symbol.stopIndex + ); + } + + return null!; + } + + private createRangeAfter(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + let stopToken = parserRuleContext.stop; + if (!stopToken) { + stopToken = parserRuleContext.start; + } + + const stop = stopToken.stopIndex; + return this._createRange(stop + 1, stop + 1); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange( + parserRuleContext.symbol.stopIndex + 1, + parserRuleContext.symbol.stopIndex + 1 + ); + } + + //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want + // to introduce a regression bug. + return null!; + } + + private _createRange(start: number, end: number): Range { + const endPosition = this.textDocument.positionAt(end); + if (endPosition.line < this.at.line) { + return Range.create(Position.create(this.at.line, 0), this.at); + } + const startPosition = this.textDocument.positionAt(start); + return Range.create(startPosition, endPosition); + } + + private thenable( + ...completionItems: CompletionItem[] + ): Promise { + return Promise.resolve(completionItems || []); + } } diff --git a/Source/mongo/services/languageService.ts b/Source/mongo/services/languageService.ts index 83b1b594e..7629c9258 100644 --- a/Source/mongo/services/languageService.ts +++ b/Source/mongo/services/languageService.ts @@ -5,86 +5,119 @@ // NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) -import { Db } from 'mongodb'; -import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; -import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; +import { Db } from "mongodb"; +import { + getLanguageService, + LanguageService as JsonLanguageService, + SchemaConfiguration, +} from "vscode-json-languageservice"; +import { + CompletionItem, + IConnection, + InitializeParams, + InitializeResult, + TextDocumentPositionParams, + TextDocuments, + TextDocumentSyncKind, +} from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { IConnectionParams } from "./IConnectionParams"; +import { MongoScriptDocumentManager } from "./mongoScript"; +import { SchemaService } from "./schemaService"; export class LanguageService { - - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] } - } - }; - }); - - connection.onCompletion(textDocumentPosition => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) - .then(account => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db) - .then(schemas => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: uri => this.schemaService.resolveSchema(uri), - contributions: [] - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas - }); - } + private textDocuments: TextDocuments = new TextDocuments( + TextDocument + ); + private readonly mongoDocumentsManager: MongoScriptDocumentManager; + private db: Db; + + private jsonLanguageService: JsonLanguageService; + private schemaService: SchemaService; + private schemas: SchemaConfiguration[]; + + constructor(connection: IConnection) { + this.schemaService = new SchemaService(); + + this.textDocuments.listen(connection); + // After the server has started the client sends an initilize request. The server receives + // in the passed params the rootPath of the workspace plus the client capabilities. + connection.onInitialize( + (_params: InitializeParams): InitializeResult => { + return { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode + completionProvider: { triggerCharacters: ["."] }, + }, + }; + } + ); + + connection.onCompletion((textDocumentPosition) => { + return this.provideCompletionItems(textDocumentPosition); + }); + + connection.onRequest( + "connect", + (connectionParams: IConnectionParams) => { + void connectToMongoClient( + connectionParams.connectionString, + connectionParams.extensionUserAgent + ).then((account) => { + this.db = account.db(connectionParams.databaseName); + void this.schemaService + .registerSchemas(this.db) + .then((schemas) => { + this.configureSchemas(schemas); + }); + }); + } + ); + + connection.onRequest("disconnect", () => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.db = null!; + for (const schema of this.schemas) { + this.jsonLanguageService.resetSchema(schema.uri); + } + }); + + this.jsonLanguageService = getLanguageService({ + schemaRequestService: (uri) => + this.schemaService.resolveSchema(uri), + contributions: [], + }); + + this.mongoDocumentsManager = new MongoScriptDocumentManager( + this.schemaService, + this.jsonLanguageService + ); + } + + public provideCompletionItems( + positionParams: TextDocumentPositionParams + ): Promise { + const textDocument = this.textDocuments.get( + positionParams.textDocument.uri + ); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const mongoScriptDocument = this.mongoDocumentsManager.getDocument( + textDocument!, + this.db + ); + return mongoScriptDocument.provideCompletionItemsAt( + positionParams.position + ); + } + + public resetSchema(uri: string): void { + this.jsonLanguageService.resetSchema(uri); + } + + public configureSchemas(schemas: SchemaConfiguration[]): void { + this.jsonLanguageService.configure({ + schemas, + }); + } } diff --git a/Source/mongo/services/mongoScript.ts b/Source/mongo/services/mongoScript.ts index 8d4c85398..4d5cb89dd 100644 --- a/Source/mongo/services/mongoScript.ts +++ b/Source/mongo/services/mongoScript.ts @@ -2,100 +2,133 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, Position } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { SchemaService } from './schemaService'; +import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; +import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; +import { Interval } from "antlr4ts/misc/Interval"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Db } from "mongodb"; +import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; +import { CompletionItem, Position } from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { mongoLexer } from "./../grammar/mongoLexer"; +import * as mongoParser from "./../grammar/mongoParser"; +import { MongoVisitor } from "./../grammar/visitors"; +import { CompletionItemsVisitor } from "./completionItemProvider"; +import { SchemaService } from "./schemaService"; export class MongoScriptDocumentManager { + constructor( + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) {} - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - } - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } + public getDocument( + textDocument: TextDocument, + db: Db + ): MongoScriptDocument { + return new MongoScriptDocument( + textDocument, + db, + this.schemaService, + this.jsonLanguageService + ); + } } export class MongoScriptDocument { + private readonly _lexer: mongoLexer; - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } + constructor( + private textDocument: TextDocument, + private db: Db, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + this._lexer = new mongoLexer(new InputStream(textDocument.getText())); + this._lexer.removeErrorListeners(); + } - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); + public provideCompletionItemsAt( + position: Position + ): Promise { + const parser = new mongoParser.mongoParser( + new CommonTokenStream(this._lexer) + ); + parser.removeErrorListeners(); - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); - } - return Promise.resolve([]); - } + const offset = this.textDocument.offsetAt(position); + const lastNode = new NodeFinder(offset).visit(parser.commands()); + if (lastNode) { + return new CompletionItemsVisitor( + this.textDocument, + this.db, + offset, + this.schemaService, + this.jsonLanguageService + ).visit(lastNode); + } + return Promise.resolve([]); + } } class NodeFinder extends MongoVisitor { + constructor(private offset: number) { + super(); + } - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } + protected defaultResult(ctx: ParseTree): ParseTree { + if (ctx instanceof ParserRuleContext) { + const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; + if (stop < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + if (ctx instanceof TerminalNode) { + if (ctx.symbol.stopIndex < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; - const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; - const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; - const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; + protected aggregateResult( + aggregate: ParseTree, + nextResult: ParseTree + ): ParseTree { + if (aggregate && nextResult) { + const aggregateStart = + aggregate instanceof ParserRuleContext + ? aggregate.start.startIndex + : (aggregate).symbol.startIndex; + const aggregateStop = + aggregate instanceof ParserRuleContext + ? aggregate.start.stopIndex + : (aggregate).symbol.stopIndex; + const nextResultStart = + nextResult instanceof ParserRuleContext + ? nextResult.start.startIndex + : (nextResult).symbol.startIndex; + const nextResultStop = + nextResult instanceof ParserRuleContext + ? nextResult.start.stopIndex + : (nextResult).symbol.stopIndex; - if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } + if ( + Interval.of(aggregateStart, aggregateStop).properlyContains( + Interval.of(nextResultStart, nextResultStop) + ) + ) { + return aggregate; + } + return nextResult; + } + return nextResult ? nextResult : aggregate; + } } diff --git a/Source/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts index cf70e8cde..acb195725 100644 --- a/Source/mongo/services/schemaService.ts +++ b/Source/mongo/services/schemaService.ts @@ -5,624 +5,726 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ -import { Cursor, Db } from 'mongodb'; -import { SchemaConfiguration } from 'vscode-json-languageservice'; +import { Cursor, Db } from "mongodb"; +import { SchemaConfiguration } from "vscode-json-languageservice"; // eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; +import { JSONSchema } from "vscode-json-languageservice/lib/umd/jsonSchema"; export class SchemaService { - - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections() - .then(collections => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push(...[{ - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)] - }, { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)] - }]); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {} - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - for (const property of Object.keys(document)) { - if (!parent && - ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'] - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' - }, - $language: { - type: 'string', - description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' - }, - $caseSensitive: { - type: 'boolean', - description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` - } - }, - required: ['$search'] - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate' - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri - } - }; - schema.properties!.$and = { - type: 'array', - description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri - } - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri - } - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {} - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value' - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value' - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value' - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value' - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value' - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value' - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array' - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array' - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field' - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type' - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0] - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression' - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type' - }, - coordinates: { - type: 'array' - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string' - }, - properties: { - type: 'object' - } - } - } - } - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array' - }, - $polygon: { - type: 'array' - }, - $center: { - type: 'array' - }, - $centerSphere: { - type: 'array' - } - } - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema - } - }; - expressionSchema.properties.$near = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query' - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size' - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties } - }; - schema.properties!.$elemMatch = { - type: 'object' - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view' - } - } - - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri - } - } - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'] - } - }, - additionalProperties: { - type: 'object' - } - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' - } - } - }); - return { - type: 'object', - oneOf: schemas - }; - } - - private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then(hasNext => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then(doc => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } - + private _db: Db; + private _schemasCache: Map = new Map(); + + public registerSchemas(db: Db): Thenable { + this._db = db; + this._schemasCache.clear(); + return this._db.collections().then((collections) => { + const schemas: SchemaConfiguration[] = []; + for (const collection of collections) { + schemas.push( + ...[ + { + uri: this.queryCollectionSchema( + collection.collectionName + ), + fileMatch: [ + this.queryDocumentUri( + collection.collectionName + ), + ], + }, + { + uri: this.aggregateCollectionSchema( + collection.collectionName + ), + fileMatch: [ + this.aggregateDocumentUri( + collection.collectionName + ), + ], + }, + ] + ); + } + return schemas; + }); + } + + public queryCollectionSchema(collectionName: string): string { + return "mongo://query/" + collectionName + ".schema"; + } + + public aggregateCollectionSchema(collectionName: string): string { + return "mongo://aggregate/" + collectionName + ".schema"; + } + + public queryDocumentUri(collectionName: string): string { + return "mongo://query/" + collectionName + ".json"; + } + + public aggregateDocumentUri(collectionName: string): string { + return "mongo://aggregate/" + collectionName + ".json"; + } + + public resolveSchema(uri: string): Thenable { + const schema = this._schemasCache.get(uri); + if (schema) { + return Promise.resolve(schema); + } + if (uri.startsWith("mongo://query/")) { + return this._resolveQueryCollectionSchema( + uri.substring( + "mongo://query/".length, + uri.length - ".schema".length + ), + uri + ).then((sch) => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + if (uri.startsWith("mongo://aggregate/")) { + return this._resolveAggregateCollectionSchema( + uri.substring( + "mongo://aggregate/".length, + uri.length - ".schema".length + ) + ).then((sch) => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + return Promise.resolve(""); + } + + private _resolveQueryCollectionSchema( + collectionName: string, + schemaUri: string + ): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (result) => { + const schema: JSONSchema = { + type: "object", + properties: {}, + }; + for (const document of result) { + this.setSchemaForDocument(null!, document, schema); + } + this.setGlobalOperatorProperties(schema); + this.setLogicalOperatorProperties(schema, schemaUri); + resolve(JSON.stringify(schema)); + }); + }); + } + + private _resolveAggregateCollectionSchema( + collectionName: string + ): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (_result) => { + const schema: JSONSchema = { + type: "array", + items: this.getAggregateStagePropertiesSchema( + this.queryCollectionSchema(collectionName) + ), + }; + resolve(JSON.stringify(schema)); + }); + }); + } + + private getMongoDocumentType(document: any): string { + return Array.isArray(document) + ? "array" + : document === null + ? "null" + : typeof document; + } + + private setSchemaForDocument( + parent: string, + document: any, + schema: JSONSchema + ): void { + if (this.getMongoDocumentType(document) === "object") { + for (const property of Object.keys(document)) { + if (!parent && ["_id"].indexOf(property) !== -1) { + continue; + } + this.setSchemaForDocumentProperty( + parent, + property, + document, + schema + ); + } + } + } + + private setSchemaForDocumentProperty( + parent: string, + property: string, + document: any, + schema: JSONSchema + ): void { + const scopedProperty = parent ? `${parent}.${property}` : property; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const value = document[property]; + const type = this.getMongoDocumentType(value); + + const propertySchema: JSONSchema = { + type: [type, "object"], + }; + this.setOperatorProperties(type, propertySchema); + schema.properties![scopedProperty] = propertySchema; + + if (type === "object") { + this.setSchemaForDocument(scopedProperty, value, schema); + } + + if (type === "array") { + for (const v of value) { + this.setSchemaForDocument(scopedProperty, v, schema); + } + } + } + + private setGlobalOperatorProperties(schema: JSONSchema): void { + schema.properties!.$text = { + type: "object", + description: "Performs text search", + properties: { + $search: { + type: "string", + description: + "A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase", + }, + $language: { + type: "string", + description: + 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming', + }, + $caseSensitive: { + type: "boolean", + description: + "Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index", + }, + $diacriticSensitive: { + type: "boolean", + description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index +Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`, + }, + }, + required: ["$search"], + }; + + schema.properties!.$where = { + type: "string", + description: `Matches documents that satisfy a JavaScript expression. +Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`, + }; + schema.properties!.$comment = { + type: "string", + description: "Adds a comment to a query predicate", + }; + } + + private setLogicalOperatorProperties( + schema: JSONSchema, + schemaUri: string + ): void { + schema.properties!.$or = { + type: "array", + description: + "Joins query clauses with a logical OR returns all documents that match the conditions of either clause", + items: { + $ref: schemaUri, + }, + }; + schema.properties!.$and = { + type: "array", + description: + "Joins query clauses with a logical AND returns all documents that match the conditions of both clauses", + items: { + $ref: schemaUri, + }, + }; + schema.properties!.$nor = { + type: "array", + description: + "Joins query clauses with a logical NOR returns all documents that fail to match both clauses", + items: { + $ref: schemaUri, + }, + }; + } + + private setOperatorProperties(type: string, schema: JSONSchema): void { + if (!schema.properties) { + schema.properties = {}; + } + + const expressionSchema = { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: {}, + }; + // Comparison operators + expressionSchema.properties.$eq = { + type: type, + description: "Matches values that are equal to a specified value", + }; + expressionSchema.properties.$gt = { + type: type, + description: + "Matches values that are greater than a specified value", + }; + expressionSchema.properties.$gte = { + type: type, + description: + "Matches values that are greater than or equal to a specified value", + }; + expressionSchema.properties.$lt = { + type: type, + description: "Matches values that are less than a specified value", + }; + expressionSchema.properties.$lte = { + type: type, + description: + "Matches values that are less than or equal to a specified value", + }; + expressionSchema.properties.$ne = { + type: type, + description: + "Matches all values that are not equal to a specified value", + }; + expressionSchema.properties.$in = { + type: "array", + description: "Matches any of the values specified in an array", + }; + expressionSchema.properties.$nin = { + type: "array", + description: "Matches none of the values specified in an array", + }; + + // Element operators + expressionSchema.properties.$exists = { + type: "boolean", + description: "Matches documents that have the specified field", + }; + expressionSchema.properties.$type = { + type: "string", + description: + "Selects documents if a field is of the specified type", + }; + + // Evaluation operators + expressionSchema.properties.$mod = { + type: "array", + description: + "Performs a modulo operation on the value of a field and selects documents with a specified result", + maxItems: 2, + default: [2, 0], + }; + expressionSchema.properties.$regex = { + type: "string", + description: + "Selects documents where values match a specified regular expression", + }; + + // Geospatial + const geometryPropertySchema: JSONSchema = { + type: "object", + properties: { + type: { + type: "string", + default: "GeoJSON object type", + }, + coordinates: { + type: "array", + }, + crs: { + type: "object", + properties: { + type: { + type: "string", + }, + properties: { + type: "object", + }, + }, + }, + }, + }; + expressionSchema.properties.$geoWithin = { + type: "object", + description: + "Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin", + properties: { + $geometry: geometryPropertySchema, + $box: { + type: "array", + }, + $polygon: { + type: "array", + }, + $center: { + type: "array", + }, + $centerSphere: { + type: "array", + }, + }, + }; + expressionSchema.properties.$geoIntersects = { + type: "object", + description: + "Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects", + properties: { + $geometry: geometryPropertySchema, + }, + }; + expressionSchema.properties.$near = { + type: "object", + description: + "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: "number", + }, + $minDistance: { + type: "number", + }, + }, + }; + expressionSchema.properties.$nearSphere = { + type: "object", + description: + "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: "number", + }, + $minDistance: { + type: "number", + }, + }, + }; + + // Array operatos + if (type === "array") { + expressionSchema.properties.$all = { + type: "array", + description: + "Matches arrays that contain all elements specified in the query", + }; + expressionSchema.properties.$size = { + type: "number", + description: + "Selects documents if the array field is a specified size", + }; + } + + // Bit operators + expressionSchema.properties.$bitsAllSet = { + type: "array", + description: + "Matches numeric or binary values in which a set of bit positions all have a value of 1", + }; + expressionSchema.properties.$bitsAnySet = { + type: "array", + description: + "Matches numeric or binary values in which any bit from a set of bit positions has a value of 1", + }; + expressionSchema.properties.$bitsAllClear = { + type: "array", + description: + "Matches numeric or binary values in which a set of bit positions all have a value of 0", + }; + expressionSchema.properties.$bitsAnyClear = { + type: "array", + description: + "Matches numeric or binary values in which any bit from a set of bit positions has a value of 0", + }; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + schema.properties = { ...expressionSchema.properties }; + schema.properties!.$not = { + type: "object", + description: + "Inverts the effect of a query expression and returns documents that do not match the query expression", + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: { ...expressionSchema.properties }, + }; + schema.properties!.$elemMatch = { + type: "object", + }; + } + + private getAggregateStagePropertiesSchema( + querySchemaUri: string + ): JSONSchema { + const schemas: JSONSchema[] = []; + schemas.push({ + type: "object", + properties: { + $collStats: { + type: "object", + description: + "Returns statistics regarding a collection or view", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $project: { + type: "object", + description: + "Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $match: { + type: "object", + description: + "Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)", + $ref: querySchemaUri, + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $redact: { + type: "object", + description: + "Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $limit: { + type: "object", + description: + "Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $skip: { + type: "object", + description: + "Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $unwind: { + type: "object", + description: + "Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $group: { + type: "object", + description: + "Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.", + properties: { + _id: { + type: ["string", "object"], + }, + }, + additionalProperties: { + type: "object", + }, + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sample: { + type: "object", + description: + "Randomly selects the specified number of documents from its input", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sort: { + type: "object", + description: + "Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $geoNear: { + type: "object", + description: + "Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $lookup: { + type: "object", + description: + "Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $out: { + type: "object", + description: + "Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $indexStats: { + type: "object", + description: + "Returns statistics regarding the use of each index for the collection", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $facet: { + type: "object", + description: + "Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $bucket: { + type: "object", + description: + "Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $bucketAuto: { + type: "object", + description: + "Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sortByCount: { + type: "object", + description: + "Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $addFields: { + type: "object", + description: + "Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $replaceRoot: { + type: "object", + description: + "Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $count: { + type: "object", + description: + "Returns a count of the number of documents at this stage of the aggregation pipeline", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $graphLookup: { + type: "object", + description: + "Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document", + }, + }, + }); + return { + type: "object", + oneOf: schemas, + }; + } + + private readNext( + result: any[], + cursor: Cursor, + batchSize: number, + callback: (result: any[]) => void + ): void { + if (result.length === batchSize) { + callback(result); + return; + } + + void cursor.hasNext().then((hasNext) => { + if (!hasNext) { + callback(result); + return; + } + + void cursor.next().then((doc) => { + result.push(doc); + this.readNext(result, cursor, batchSize, callback); + }); + }); + } } diff --git a/Source/mongo/setConnectedNode.ts b/Source/mongo/setConnectedNode.ts index f5680d09d..bcb8e95e1 100644 --- a/Source/mongo/setConnectedNode.ts +++ b/Source/mongo/setConnectedNode.ts @@ -6,8 +6,10 @@ import { ext } from "../extensionVariables"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); +export function setConnectedNode( + node: MongoDatabaseTreeItem | undefined +): void { + ext.connectedMongoDB = node; + const dbName = node && node.label; + ext.mongoCodeLensProvider.setConnectedDatabase(dbName); } diff --git a/Source/mongo/tree/IMongoTreeRoot.ts b/Source/mongo/tree/IMongoTreeRoot.ts index d9b68980d..262e03876 100644 --- a/Source/mongo/tree/IMongoTreeRoot.ts +++ b/Source/mongo/tree/IMongoTreeRoot.ts @@ -1,9 +1,8 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ export interface IMongoTreeRoot { - isEmulator: boolean | undefined; + isEmulator: boolean | undefined; } diff --git a/Source/mongo/tree/MongoAccountTreeItem.ts b/Source/mongo/tree/MongoAccountTreeItem.ts index baa870c23..2f4621afb 100644 --- a/Source/mongo/tree/MongoAccountTreeItem.ts +++ b/Source/mongo/tree/MongoAccountTreeItem.ts @@ -3,138 +3,191 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; -import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + AzExtTreeItem, + ICreateChildImplContext, + parseError, +} from "@microsoft/vscode-azext-utils"; +import { MongoClient } from "mongodb"; +import * as vscode from "vscode"; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; +import { getThemeAgnosticIconPath, Links, testDb } from "../../constants"; +import { nonNullProp } from "../../utils/nonNull"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { getDatabaseNameFromConnectionString } from "../mongoConnectionStrings"; +import { IMongoTreeRoot } from "./IMongoTreeRoot"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; +import { MongoDatabaseTreeItem } from "./MongoDatabaseTreeItem"; +import { MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error('Missing connection string'); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); - - const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [{ - name: databaseInConnectionString, - empty: false - }]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); - databases = result.databases; - } - return databases - .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty - .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } - finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createMongoDatabase', - validateInput: validateDatabaseName - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public static contextValue: string = "cosmosDBMongoServer"; + public readonly contextValue: string = MongoAccountTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly label: string; + public readonly connectionString: string; + + private _root: IMongoTreeRoot; + + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + connectionString: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super(parent); + this.id = id; + this.label = label; + this.connectionString = connectionString; + this._root = { isEmulator }; + this.valuesToMask.push(connectionString); + } + + // overrides ISubscriptionContext with an object that also has Mongo info + public get root(): IMongoTreeRoot { + return this._root; + } + + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("CosmosDBAccount.svg"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + let mongoClient: MongoClient | undefined; + try { + let databases: IDatabaseInfo[]; + + if (!this.connectionString) { + throw new Error("Missing connection string"); + } + + // Azure MongoDB accounts need to have the name passed in for private endpoints + mongoClient = await connectToMongoClient( + this.connectionString, + this.databaseAccount + ? nonNullProp(this.databaseAccount, "name") + : appendExtensionUserAgent() + ); + + const databaseInConnectionString = + getDatabaseNameFromConnectionString(this.connectionString); + if (databaseInConnectionString && !this.root.isEmulator) { + // emulator violates the connection string format + // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) + databases = [ + { + name: databaseInConnectionString, + empty: false, + }, + ]; + } else { + // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: { databases: IDatabaseInfo[] } = await mongoClient + .db(testDb) + .admin() + .listDatabases(); + databases = result.databases; + } + return databases + .filter( + (database: IDatabaseInfo) => + !( + database.name && + database.name.toLowerCase() === "admin" && + database.empty + ) + ) // Filter out the 'admin' database if it's empty + .map( + (database) => + new MongoDatabaseTreeItem( + this, + nonNullProp(database, "name"), + this.connectionString + ) + ); + } catch (error) { + const message = parseError(error).message; + if (this._root.isEmulator && message.includes("ECONNREFUSED")) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; + } + throw error; + } finally { + if (mongoClient) { + void mongoClient.close(); + } + } + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: "createMongoDatabase", + validateInput: validateDatabaseName, + }); + context.showCreatingTreeItem(databaseName); + + return new MongoDatabaseTreeItem( + this, + databaseName, + this.connectionString + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case MongoDatabaseTreeItem.contextValue: + case MongoCollectionTreeItem.contextValue: + case MongoDocumentTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } } -export function validateDatabaseName(database: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return "Database name cannot contain these characters - `/\\. \"$#?=`"; - } - return undefined; +export function validateDatabaseName( + database: string +): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions + // "#?" are restricted characters for CosmosDB - MongoDB accounts + const min = 1; + const max = 63; + if (!database || database.length < min || database.length > max) { + return `Database name must be between ${min} and ${max} characters.`; + } + if (/[/\\. "$#?=]/.test(database)) { + return 'Database name cannot contain these characters - `/\\. "$#?=`'; + } + return undefined; } export interface IDatabaseInfo { - name?: string; - empty?: boolean; + name?: string; + empty?: boolean; } diff --git a/Source/mongo/tree/MongoCollectionTreeItem.ts b/Source/mongo/tree/MongoCollectionTreeItem.ts index eca0c8d32..b4dd4f68f 100644 --- a/Source/mongo/tree/MongoCollectionTreeItem.ts +++ b/Source/mongo/tree/MongoCollectionTreeItem.ts @@ -5,316 +5,473 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullValue } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { MongoCommand } from '../MongoCommand'; -import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as assert from "assert"; +import { + BulkWriteOpResultObject, + Collection, + CollectionInsertManyOptions, + Cursor, + DeleteWriteOpResultObject, + InsertOneWriteOpResult, + InsertWriteOpResult, + MongoCountPreferences, +} from "mongodb"; +import * as _ from "underscore"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullValue } from "../../utils/nonNull"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { getBatchSizeSetting } from "../../utils/workspacUtils"; +import { MongoCommand } from "../MongoCommand"; +import { IMongoDocument, MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; type MongoDocument = { _id: string }; class FunctionDescriptor { - public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { - } + public constructor( + public mongoFunction: MongoFunction, + public text: string, + public minShellArgs: number, + public maxShellArgs: number, + public maxHandledArgs: number + ) {} } -export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, '_id'), - upsert: false - } - }; - }); - - const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = await this.getCachedChildren(context); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(children.map(c => c.document), null, 2); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get filePath(): string { - return this.label + '-cosmos-collection.json'; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { - const documentNodes = await this.getCachedChildren(context); - for (const doc of docs) { - const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection.find(this._query).batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - 'invalidMongoDocument', - doc => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; - - const functions = { - drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), - count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), - findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), - insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), - insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), - insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), - deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), - deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), - remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error(`Too few arguments passed to command ${command.name}.`); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error(`Too many arguments passed to command ${command.name}`); - } - if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number, name?: string } = e; - const NamespaceNotFoundCode = 26; - if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne(query?: Object, fieldsOption?: Object): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, '\t'); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error("The insert command requires at least one argument"); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count(query?: Object[], options?: MongoCountPreferences): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, '\t'); - } +export class MongoCollectionTreeItem + extends AzExtParentTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "MongoCollection"; + public readonly contextValue: string = MongoCollectionTreeItem.contextValue; + public readonly childTypeLabel: string = "Document"; + public readonly collection: Collection; + public parent: AzExtParentTreeItem; + public findArgs?: {}[]; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + + private readonly _query: object | undefined; + private readonly _projection: object | undefined; + private _cursor: Cursor | undefined; + private _hasMoreChildren: boolean = true; + private _batchSize: number = getBatchSizeSetting(); + + constructor( + parent: AzExtParentTreeItem, + collection: Collection, + findArgs?: {}[] + ) { + super(parent); + this.collection = collection; + this.findArgs = findArgs; + if (findArgs && findArgs.length) { + this._query = findArgs[0]; + this._projection = findArgs.length > 1 ? findArgs[1] : undefined; + } + ext.fileSystem.fireChangedEvent(this); + } + + public async writeFileContent( + context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const documents: IMongoDocument[] = EJSON.parse(content); + const operations = documents.map((document) => { + return { + replaceOne: { + filter: { _id: document._id }, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + replacement: _.omit(document, "_id"), + upsert: false, + }, + }; + }); + + const result: BulkWriteOpResultObject = + await this.collection.bulkWrite(operations); + ext.outputChannel.appendLog( + `Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)` + ); + + // The current tree item may have been a temporary one used to execute a scrapbook command. + // We want to refresh children for this one _and_ the actual one in the tree (if it's different) + const nodeInTree: MongoCollectionTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); + const nodesToRefresh: MongoCollectionTreeItem[] = [this]; + if (nodeInTree && this !== nodeInTree) { + nodesToRefresh.push(nodeInTree); + } + + await Promise.all( + nodesToRefresh.map((n) => n.refreshChildren(context, documents)) + ); + + if (nodeInTree && this !== nodeInTree) { + // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different + ext.fileSystem.fireChangedEvent(nodeInTree); + } + } + + public async getFileContent(context: IActionContext): Promise { + const children = ( + await this.getCachedChildren(context) + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify( + children.map((c) => c.document), + null, + 2 + ); + } + + public get id(): string { + return this.collection.collectionName; + } + + public get label(): string { + return this.collection.collectionName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get filePath(): string { + return this.label + "-cosmos-collection.json"; + } + + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + ext.fileSystem.fireChangedEvent(this); + } + + public async refreshChildren( + context: IActionContext, + docs: IMongoDocument[] + ): Promise { + const documentNodes = ( + await this.getCachedChildren(context) + ); + for (const doc of docs) { + const documentNode = documentNodes.find( + (node) => node.document._id.toString() === doc._id.toString() + ); + if (documentNode) { + documentNode.document = doc; + await documentNode.refresh(context); + } + } + } + + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } + + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache || this._cursor === undefined) { + this._cursor = this.collection + .find(this._query) + .batchSize(this._batchSize); + if (this._projection) { + this._cursor = this._cursor.project(this._projection); + } + } + + const documents: IMongoDocument[] = []; + let count: number = 0; + while (count < this._batchSize) { + this._hasMoreChildren = await this._cursor.hasNext(); + if (this._hasMoreChildren) { + documents.push(await this._cursor.next()); + count += 1; + } else { + break; + } + } + this._batchSize *= 2; + + return this.createTreeItemsWithErrorHandling( + documents, + "invalidMongoDocument", + (doc) => new MongoDocumentTreeItem(this, doc), + getDocumentTreeItemLabel + ); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + context.showCreatingTreeItem(""); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: InsertOneWriteOpResult = + await this.collection.insertOne({}); + const newDocument: IMongoDocument = nonNullValue( + await this.collection.findOne({ _id: result.insertedId }), + "newDocument" + ); + return new MongoDocumentTreeItem(this, newDocument); + } + + public async tryExecuteCommandDirectly( + command: Partial + ): Promise< + | { deferToShell: true; result: undefined } + | { deferToShell: false; result: string } + > { + // range and text are not neccessary properties for this function so partial should suffice + const parameters = command.arguments + ? command.arguments.map(parseJSContent) + : []; + + const functions = { + drop: new FunctionDescriptor( + this.drop, + "Dropping collection", + 0, + 0, + 0 + ), + count: new FunctionDescriptor( + this.count, + "Counting documents", + 0, + 2, + 2 + ), + findOne: new FunctionDescriptor( + this.findOne, + "Finding document", + 0, + 2, + 2 + ), + insert: new FunctionDescriptor( + this.insert, + "Inserting document", + 1, + 1, + 1 + ), + insertMany: new FunctionDescriptor( + this.insertMany, + "Inserting documents", + 1, + 2, + 2 + ), + insertOne: new FunctionDescriptor( + this.insertOne, + "Inserting document", + 1, + 2, + 2 + ), + deleteMany: new FunctionDescriptor( + this.deleteMany, + "Deleting documents", + 1, + 2, + 1 + ), + deleteOne: new FunctionDescriptor( + this.deleteOne, + "Deleting document", + 1, + 2, + 1 + ), + remove: new FunctionDescriptor( + this.remove, + "Deleting document(s)", + 1, + 2, + 1 + ), + }; + + // eslint-disable-next-line no-prototype-builtins + if (command.name && functions.hasOwnProperty(command.name)) { + // currently no logic to handle chained commands so just defer to the shell right away + if (command.chained) { + return { deferToShell: true, result: undefined }; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const descriptor: FunctionDescriptor = functions[command.name]; + + if (parameters.length < descriptor.minShellArgs) { + throw new Error( + `Too few arguments passed to command ${command.name}.` + ); + } + if (parameters.length > descriptor.maxShellArgs) { + throw new Error( + `Too many arguments passed to command ${command.name}` + ); + } + if (parameters.length > descriptor.maxHandledArgs) { + //this function won't handle these arguments, but the shell will + return { deferToShell: true, result: undefined }; + } + const result = await reportProgress( + descriptor.mongoFunction.apply(this, parameters), + descriptor.text + ); + return { deferToShell: false, result }; + } + return { deferToShell: true, result: undefined }; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoCollection" }, + DialogResponses.deleteResponse + ); + await this.drop(); + } + + private async drop(): Promise { + try { + await this.collection.drop(); + return `Dropped collection '${this.collection.collectionName}'.`; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const error: { code?: number; name?: string } = e; + const NamespaceNotFoundCode = 26; + if ( + error.name === "MongoError" && + error.code === NamespaceNotFoundCode + ) { + return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; + } else { + throw error; + } + } + } + + private async findOne( + query?: Object, + fieldsOption?: Object + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = await this.collection.findOne(query || {}, { + fields: fieldsOption, + }); + // findOne is the only command in this file whose output requires EJSON support. + // Hence that's the only function which uses EJSON.stringify rather than this.stringify. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(result, null, "\t"); + } + + private async insert(document: Object): Promise { + if (!document) { + throw new Error( + "The insert command requires at least one argument" + ); + } + + const insertResult = await this.collection.insert(document); + return this.stringify(insertResult); + } + + private async insertOne(document: Object, options?: any): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const insertOneResult: InsertOneWriteOpResult = + await this.collection.insertOne(document, { + w: options && options.writeConcern, + }); + return this.stringify(insertOneResult); + } + + private async insertMany(documents: any[], options?: any): Promise { + assert.notEqual( + documents.length, + 0, + "Array of documents cannot be empty" + ); + const insertManyOptions: CollectionInsertManyOptions = {}; + if (options) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.ordered) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.ordered = options.ordered; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.writeConcern) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.w = options.writeConcern; + } + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const insertManyResult: InsertWriteOpResult = + await this.collection.insertMany(documents, insertManyOptions); + return this.stringify(insertManyResult); + } + + private async remove(filter: Object): Promise { + const removeResult = await this.collection.remove(filter); + return this.stringify(removeResult); + } + + private async deleteOne(filter: Object): Promise { + const deleteOneResult: DeleteWriteOpResultObject = + await this.collection.deleteOne(filter); + return this.stringify(deleteOneResult); + } + + private async deleteMany(filter: Object): Promise { + const deleteOpResult: DeleteWriteOpResultObject = + await this.collection.deleteMany(filter); + return this.stringify(deleteOpResult); + } + + private async count( + query?: Object[], + options?: MongoCountPreferences + ): Promise { + const count = await this.collection.count(query, options); + return this.stringify(count); + } + + private stringify(result: any): string { + return JSON.stringify(result, null, "\t"); + } } function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title - }, - (_progress) => { - return promise; - }); + return vscode.window.withProgress( + { + location: vscode.ProgressLocation.Window, + title: title, + }, + (_progress) => { + return promise; + } + ); } function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.parse(content); + } catch (error) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + throw error.message; + } } diff --git a/Source/mongo/tree/MongoDatabaseTreeItem.ts b/Source/mongo/tree/MongoDatabaseTreeItem.ts index 73a7c6a22..1fed13c80 100644 --- a/Source/mongo/tree/MongoDatabaseTreeItem.ts +++ b/Source/mongo/tree/MongoDatabaseTreeItem.ts @@ -3,256 +3,383 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import { Collection, Db, DbCollectionOptions } from 'mongodb'; -import * as path from 'path'; -import * as process from 'process'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { MongoCommand } from '../MongoCommand'; -import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; -import { MongoShell } from '../MongoShell'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoAccountTreeItem } from './MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, + UserCancelledError, +} from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import { Collection, Db, DbCollectionOptions } from "mongodb"; +import * as path from "path"; +import * as process from "process"; +import * as vscode from "vscode"; +import { ext } from "../../extensionVariables"; +import * as cpUtils from "../../utils/cp"; +import { nonNullProp, nonNullValue } from "../../utils/nonNull"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { MongoCommand } from "../MongoCommand"; +import { addDatabaseToAccountConnectionString } from "../mongoConnectionStrings"; +import { MongoShell } from "../MongoShell"; +import { IMongoTreeRoot } from "./IMongoTreeRoot"; +import { MongoAccountTreeItem } from "./MongoAccountTreeItem"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; + +const mongoExecutableFileName = + process.platform === "win32" ? "mongo.exe" : "mongo"; const executingInShellMsg = "Executing command in Mongo shell"; export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map(collection => new MongoCollectionTreeItem(this, collection)); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: 'createMongoCollection', - validateInput: validateMongoCollectionName - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); - return accountConnection.db(this.databaseName); - } - - public async executeCommand(command: MongoCommand, context: IActionContext): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); - const result = await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - - } - - if (command.name === 'createCollection') { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); - } else { - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - } - } - - public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection(collectionName, options); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); - - if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); - return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); - } - - private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongo', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongo'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; - const browse: vscode.MessageItem = { title: 'Open installation page' }; - const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; - const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; - const tryAgain: vscode.MessageItem = { title: 'Try again' }; - const response2 = await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } + public static contextValue: string = "mongoDb"; + public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; + public readonly connectionString: string; + public readonly databaseName: string; + public readonly parent: MongoAccountTreeItem; + + private _previousShellPathSetting: string | undefined; + private _cachedShellPathOrCmd: string | undefined; + + constructor( + parent: MongoAccountTreeItem, + databaseName: string, + connectionString: string + ) { + super(parent); + this.databaseName = databaseName; + this.connectionString = addDatabaseToAccountConnectionString( + connectionString, + this.databaseName + ); + } + + public get root(): IMongoTreeRoot { + return this.parent.root; + } + + public get label(): string { + return this.databaseName; + } + + public get description(): string { + return ext.connectedMongoDB && + ext.connectedMongoDB.fullId === this.fullId + ? "Connected" + : ""; + } + + public get id(): string { + return this.databaseName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("database"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const db: Db = await this.connectToDb(); + const collections: Collection[] = await db.collections(); + return collections.map( + (collection) => new MongoCollectionTreeItem(this, collection) + ); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const collectionName = await context.ui.showInputBox({ + placeHolder: "Collection Name", + prompt: "Enter the name of the collection", + stepName: "createMongoCollection", + validateInput: validateMongoCollectionName, + }); + + context.showCreatingTreeItem(collectionName); + return await this.createCollection(collectionName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoDatabase" }, + DialogResponses.deleteResponse + ); + const db = await this.connectToDb(); + await db.dropDatabase(); + } + + public async connectToDb(): Promise { + const accountConnection = await connectToMongoClient( + this.connectionString, + appendExtensionUserAgent() + ); + return accountConnection.db(this.databaseName); + } + + public async executeCommand( + command: MongoCommand, + context: IActionContext + ): Promise { + if (command.collection) { + const db = await this.connectToDb(); + const collection = db.collection(command.collection); + if (collection) { + const collectionTreeItem = new MongoCollectionTreeItem( + this, + collection, + command.arguments + ); + const result = + await collectionTreeItem.tryExecuteCommandDirectly(command); + if (!result.deferToShell) { + return result.result; + } + } + return withProgress( + this.executeCommandInShell(command, context), + executingInShellMsg + ); + } + + if (command.name === "createCollection") { + // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead + return withProgress( + this.createCollection( + stripQuotes(nonNullProp(command, "arguments")[0]), + nonNullProp(command, "argumentObjects")[1] + ).then(() => JSON.stringify({ Created: "Ok" })), + "Creating collection" + ); + } else { + return withProgress( + this.executeCommandInShell(command, context), + executingInShellMsg + ); + } + } + + public async createCollection( + collectionName: string, + options?: DbCollectionOptions + ): Promise { + const db: Db = await this.connectToDb(); + const newCollection: Collection = await db.createCollection( + collectionName, + options + ); + // db.createCollection() doesn't create empty collections for some reason + // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection + const result = await newCollection.insertOne({}); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + await newCollection.deleteOne({ _id: result.insertedId }); + return new MongoCollectionTreeItem(this, newCollection); + } + + private async executeCommandInShell( + command: MongoCommand, + context: IActionContext + ): Promise { + context.telemetry.properties.executeInShell = "true"; + + if (this.root.isEmulator) { + // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info + await this.connectToDb(); + } + + // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state + // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out + // requests. + const shell = await this.createShell(context); + try { + await shell.useDatabase(this.databaseName); + return await shell.executeScript(command.text); + } finally { + shell.dispose(); + } + } + + private async createShell(context: IActionContext): Promise { + const config = vscode.workspace.getConfiguration(); + let shellPath: string | undefined = config.get( + ext.settingsKeys.mongoShellPath + ); + const shellArgs: string[] = config.get( + ext.settingsKeys.mongoShellArgs, + [] + ); + + if ( + !shellPath || + !this._cachedShellPathOrCmd || + this._previousShellPathSetting !== shellPath + ) { + // Only do this if setting changed since last time + shellPath = await this._determineShellPathOrCmd(context, shellPath); + this._previousShellPathSetting = shellPath; + } + this._cachedShellPathOrCmd = shellPath; + + const timeout = + 1000 * + nonNullValue( + config.get(ext.settingsKeys.mongoShellTimeout), + "mongoShellTimeout" + ); + return MongoShell.create( + shellPath, + shellArgs, + this.connectionString, + this.root.isEmulator, + ext.outputChannel, + timeout + ); + } + + private async _determineShellPathOrCmd( + context: IActionContext, + shellPathSetting: string | undefined + ): Promise { + if (!shellPathSetting) { + // User hasn't specified the path + if (await cpUtils.commandSucceeds("mongo", "--version")) { + // If the user already has mongo in their system path, just use that + return "mongo"; + } else { + // If all else fails, prompt the user for the mongo path + const openFile: vscode.MessageItem = { + title: `Browse to ${mongoExecutableFileName}`, + }; + const browse: vscode.MessageItem = { + title: "Open installation page", + }; + const noMongoError: string = + "This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting."; + const response = await context.ui.showWarningMessage( + noMongoError, + { stepName: "promptForMongoPath" }, + browse, + openFile + ); + if (response === openFile) { + // eslint-disable-next-line no-constant-condition + while (true) { + const newPath: vscode.Uri[] = + await context.ui.showOpenDialog({ + filters: { + "Executable Files": [ + process.platform === "win32" + ? "exe" + : "", + ], + }, + openLabel: `Select ${mongoExecutableFileName}`, + stepName: "openMongoExeFile", + }); + const fsPath = newPath[0].fsPath; + const baseName = path.basename(fsPath); + if (baseName !== mongoExecutableFileName) { + const useAnyway: vscode.MessageItem = { + title: "Use anyway", + }; + const tryAgain: vscode.MessageItem = { + title: "Try again", + }; + const response2 = + await context.ui.showWarningMessage( + `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, + { stepName: "confirmMongoExeFile" }, + useAnyway, + tryAgain + ); + if (response2 === tryAgain) { + continue; + } + } + + await vscode.workspace + .getConfiguration() + .update( + ext.settingsKeys.mongoShellPath, + fsPath, + vscode.ConfigurationTarget.Global + ); + return fsPath; + } + } else if (response === browse) { + void vscode.commands.executeCommand( + "vscode.open", + vscode.Uri.parse( + "https://docs.mongodb.com/manual/installation/" + ) + ); + // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath + } + + throw new UserCancelledError("createShell"); + } + } else { + // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix + if (await fse.pathExists(shellPathSetting)) { + const stat = await fse.stat(shellPathSetting); + if (stat.isDirectory()) { + return path.join(shellPathSetting, mongoExecutableFileName); + } + } + + return shellPathSetting; + } + } } -export function validateMongoCollectionName(collectionName: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; +export function validateMongoCollectionName( + collectionName: string +): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names + if (!collectionName) { + return "Collection name cannot be empty"; + } + const systemPrefix = "system."; + if (collectionName.startsWith(systemPrefix)) { + return `"${systemPrefix}" prefix is reserved for internal use`; + } + if (/[$]/.test(collectionName)) { + return "Collection name cannot contain $"; + } + return undefined; } -function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title - }, - (_progress) => { - return promise; - }); +function withProgress( + promise: Thenable, + title: string, + location: vscode.ProgressLocation = vscode.ProgressLocation.Window +): Thenable { + return vscode.window.withProgress( + { + location: location, + title: title, + }, + (_progress) => { + return promise; + } + ); } export function stripQuotes(term: string): string { - if ((term.startsWith('\'') && term.endsWith('\'')) - || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; + if ( + (term.startsWith("'") && term.endsWith("'")) || + (term.startsWith('"') && term.endsWith('"')) + ) { + return term.substring(1, term.length - 1); + } + return term; } diff --git a/Source/mongo/tree/MongoDocumentTreeItem.ts b/Source/mongo/tree/MongoDocumentTreeItem.ts index ad44e43c3..dae87ed84 100644 --- a/Source/mongo/tree/MongoDocumentTreeItem.ts +++ b/Source/mongo/tree/MongoDocumentTreeItem.ts @@ -3,95 +3,131 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { + Collection, + DeleteWriteOpResultObject, + ObjectID, + UpdateWriteOpResult, +} from "mongodb"; +import * as _ from "underscore"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); export interface IMongoDocument { - _id: string | ObjectID; + _id: string | ObjectID; - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + // custom properties + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [key: string]: any; } -export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); +export class MongoDocumentTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "MongoDocument"; + public readonly contextValue: string = MongoDocumentTreeItem.contextValue; + public document: IMongoDocument; + public readonly parent: MongoCollectionTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); - private _label: string; + private _label: string; - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = 'cosmosDB.openDocument'; - ext.fileSystem.fireChangedEvent(this); - } + constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { + super(parent); + this.document = document; + this._label = getDocumentTreeItemLabel(this.document); + this.commandId = "cosmosDB.openDocument"; + ext.fileSystem.fireChangedEvent(this); + } - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } + public get id(): string { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return String(this.document!._id); + } - public get label(): string { - return this._label; - } + public get label(): string { + return this._label; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("file"); + } - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } + public get filePath(): string { + return this.label + "-cosmos-document.json"; + } - public static async update(collection: Collection, newDocument: IMongoDocument): Promise { - if (!newDocument._id) { - throw new Error(`The "_id" field is required to update a document.`); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); - if (result.modifiedCount !== 1) { - throw new Error(`Failed to update document with _id '${newDocument._id}'.`); - } - return newDocument; - } + public static async update( + collection: Collection, + newDocument: IMongoDocument + ): Promise { + if (!newDocument._id) { + throw new Error( + `The "_id" field is required to update a document.` + ); + } + const filter: object = { _id: newDocument._id }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const result: UpdateWriteOpResult = await collection.replaceOne( + filter, + _.omit(newDocument, "_id") + ); + if (result.modifiedCount !== 1) { + throw new Error( + `Failed to update document with _id '${newDocument._id}'.` + ); + } + return newDocument; + } - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } + public async getFileContent(): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(this.document, null, 2); + } - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this.document); + ext.fileSystem.fireChangedEvent(this); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); - const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error(`Failed to delete document with _id '${this.document._id}'.`); - } - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this._label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoDocument" }, + DialogResponses.deleteResponse + ); + const deleteResult: DeleteWriteOpResultObject = + await this.parent.collection.deleteOne({ _id: this.document._id }); + if (deleteResult.deletedCount !== 1) { + throw new Error( + `Failed to delete document with _id '${this.document._id}'.` + ); + } + } - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); - } + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const newDocument: IMongoDocument = EJSON.parse(content); + this.document = await MongoDocumentTreeItem.update( + this.parent.collection, + newDocument + ); + } } diff --git a/Source/postgres/abstract/AbstractPostgresClient.ts b/Source/postgres/abstract/AbstractPostgresClient.ts index c1fa29c4f..ca6bd3d9a 100644 --- a/Source/postgres/abstract/AbstractPostgresClient.ts +++ b/Source/postgres/abstract/AbstractPostgresClient.ts @@ -6,18 +6,26 @@ import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; +import { + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../../utils/azureClients"; import { PostgresServerType } from "./models"; -export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; +export type AbstractPostgresClient = + | PostgreSQLFlexibleManagementClient + | PostgreSQLSingleManagementClient; -export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context) - case PostgresServerType.Single: - return await createPostgreSQLClient(context) - default: - throw new Error("Service not implemented."); - } +export async function createAbstractPostgresClient( + serverType: PostgresServerType, + context: AzExtClientContext +): Promise { + switch (serverType) { + case PostgresServerType.Flexible: + return await createPostgreSQLFlexibleClient(context); + case PostgresServerType.Single: + return await createPostgreSQLClient(context); + default: + throw new Error("Service not implemented."); + } } diff --git a/Source/postgres/abstract/models.ts b/Source/postgres/abstract/models.ts index 6bdadf16a..046185de1 100644 --- a/Source/postgres/abstract/models.ts +++ b/Source/postgres/abstract/models.ts @@ -7,49 +7,58 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; export enum PostgresServerType { - Flexible = 'Flexible', - Single = 'Single' + Flexible = "Flexible", + Single = "Single", } -export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } +export type PostgresAbstractServer = ( + | SingleModels.Server + | FlexibleModels.Server +) & { serverType?: PostgresServerType }; -export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; +export type PostgresAbstractDatabase = + | SingleModels.Database + | FlexibleModels.Database; /** * Billing information related properties of a server. */ export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; + /** + * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + */ + name: string; + /** + * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', + * 'GeneralPurpose', 'MemoryOptimized' + */ + tier: SingleModels.SkuTier | FlexibleModels.SkuTier; + /** + * The scale up/out capacity, representing server's compute units. + */ + capacity?: number; + /** + * The size code, to be interpreted by resource as appropriate. + */ + size?: string; + /** + * The family of hardware. + */ + family?: string; } export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; + location: string; + sku: AbstractSku; + administratorLogin: string; + administratorLoginPassword: string; + size: number; } -export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; +export type AbstractNameAvailability = + | SingleModels.NameAvailability + | FlexibleModels.NameAvailability; -export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; +export type AbstractFirewallRule = + | SingleModels.FirewallRule + | FlexibleModels.FirewallRule; diff --git a/Source/postgres/commands/checkAuthentication.ts b/Source/postgres/commands/checkAuthentication.ts index 6799d060c..c26bc25be 100644 --- a/Source/postgres/commands/checkAuthentication.ts +++ b/Source/postgres/commands/checkAuthentication.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; +import { + IActionContext, + IParsedError, + parseError, +} from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; import { invalidCredentialsErrorType } from "../postgresConstants"; import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; @@ -11,26 +15,34 @@ import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; import { configurePostgresFirewall } from "./configurePostgresFirewall"; import { enterPostgresCredentials } from "./enterPostgresCredentials"; -export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); +export async function checkAuthentication( + context: IActionContext, + treeItem: PostgresDatabaseTreeItem +): Promise { + let clientConfig: ClientConfig | undefined; + while (!clientConfig) { + const isFirewallRuleSet = + await treeItem.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + await configurePostgresFirewall(context, treeItem.parent); + continue; + } + try { + const getClientConfigResult = + await PostgresClientConfigFactory.getClientConfigFromNode( + treeItem.parent, + treeItem.databaseName + ); + clientConfig = getClientConfigResult.clientConfig; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; + if (parsedError.errorType === invalidCredentialsErrorType) { + await enterPostgresCredentials(context, treeItem.parent); + } else { + throw error; + } + } + } + return clientConfig; } diff --git a/Source/postgres/commands/configurePostgresFirewall.ts b/Source/postgres/commands/configurePostgresFirewall.ts index 52a378fca..86779ff9b 100644 --- a/Source/postgres/commands/configurePostgresFirewall.ts +++ b/Source/postgres/commands/configurePostgresFirewall.ts @@ -4,66 +4,102 @@ *--------------------------------------------------------------------------------------------*/ import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { getPublicIpv4 } from "../../utils/getIp"; import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; +import { nonNullProp } from "../../utils/nonNull"; +import { randomUtils } from "../../utils/randomUtils"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../abstract/AbstractPostgresClient"; +import { AbstractFirewallRule, PostgresServerType } from "../abstract/models"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function configurePostgresFirewall( + context: IActionContext, + treeItem?: PostgresServerTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), - { - modal: true, - stepName: 'postgresAddFirewallRule' - }, - { title: DialogResponses.yes.title } - ); + const ip: string = await getPublicIp(context); + await context.ui.showWarningMessage( + localize( + "firewallRuleWillBeAdded", + 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', + ip, + treeItem.label + ), + { + modal: true, + stepName: "postgresAddFirewallRule", + }, + { title: DialogResponses.yes.title } + ); - await setFirewallRule(context, treeItem, ip); + await setFirewallRule(context, treeItem, ip); } -export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { +export async function setFirewallRule( + context: IActionContext, + treeItem: PostgresServerTreeItem, + ip: string +): Promise { + const serverType: PostgresServerType = nonNullProp(treeItem, "serverType"); + const client: AbstractPostgresClient = await createAbstractPostgresClient( + serverType, + [context, treeItem.subscription] + ); + const resourceGroup: string = nonNullProp(treeItem, "resourceGroup"); + const serverName: string = nonNullProp(treeItem, "azureName"); - const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); - const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); - const serverName: string = nonNullProp(treeItem, 'azureName'); + const firewallRuleName: string = + "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; + const newFirewallRule: AbstractFirewallRule = { + startIpAddress: ip, + endIpAddress: ip, + }; - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip - }; - - const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); - }); - const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); + const progressMessage: string = localize( + "configuringFirewallRule", + 'Adding firewall rule for IP "{0}" to server "{1}"...', + ip, + serverName + ); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage, + }; + ext.outputChannel.appendLog(progressMessage); + await vscode.window.withProgress(options, async () => { + await client.firewallRules.beginCreateOrUpdateAndWait( + resourceGroup, + serverName, + firewallRuleName, + newFirewallRule + ); + }); + const completedMessage: string = localize( + "addedFirewallRule", + 'Successfully added firewall rule for IP "{0}" to server "{1}".', + ip, + serverName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + await treeItem.refresh(context); } export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); + return await getPublicIpv4(context); } diff --git a/Source/postgres/commands/connectPostgresDatabase.ts b/Source/postgres/commands/connectPostgresDatabase.ts index 6996f7d03..9437c8c70 100644 --- a/Source/postgres/commands/connectPostgresDatabase.ts +++ b/Source/postgres/commands/connectPostgresDatabase.ts @@ -4,36 +4,52 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from 'vscode'; -import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { Uri, window } from "vscode"; +import { + connectedPostgresKey, + postgresFlexibleFilter, + postgresSingleFilter, +} from "../../constants"; import { ext } from "../../extensionVariables"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } +export async function connectPostgresDatabase( + context: IActionContext, + treeItem?: Uri | PostgresDatabaseTreeItem +): Promise { + if (!treeItem || treeItem instanceof Uri) { + if (treeItem) { + void window.showTextDocument(treeItem); + } + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); + const oldTreeItemId: string | undefined = + ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; + void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); + ext.connectedPostgresDB = treeItem; + const database = treeItem && treeItem.label; + if (ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(database); + } + await treeItem.refresh(context); - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } + if (oldTreeItemId) { + // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldTreeItem: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + oldTreeItemId, + context + ); + if (oldTreeItem) { + await oldTreeItem.refresh(context); + } + } } diff --git a/Source/postgres/commands/copyConnectionString.ts b/Source/postgres/commands/copyConnectionString.ts index 716bbd5b6..6d9bcbcf2 100644 --- a/Source/postgres/commands/copyConnectionString.ts +++ b/Source/postgres/commands/copyConnectionString.ts @@ -3,34 +3,56 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { + addDatabaseToConnectionString, + copyPostgresConnectionString, +} from "../postgresConnectionStrings"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { checkAuthentication } from "./checkAuthentication"; -export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } +export async function copyConnectionString( + context: IActionContext, + node: PostgresDatabaseTreeItem +): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); - } else { - connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); - } + await checkAuthentication(context, node); + const parsedConnectionString = await node.parent.getFullConnectionString(); + let connectionString: string; + if (node.parent.azureName) { + const parsedCS = await node.parent.getFullConnectionString(); + connectionString = copyPostgresConnectionString( + parsedCS.hostName, + parsedCS.port, + parsedCS.username, + parsedCS.password, + node.databaseName + ); + } else { + connectionString = addDatabaseToConnectionString( + parsedConnectionString.connectionString, + node.databaseName + ); + } - await vscode.env.clipboard.writeText(connectionString); - const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); - void vscode.window.showInformationMessage(message); + await vscode.env.clipboard.writeText(connectionString); + const message = localize( + "copiedPostgresConnectStringMsg", + "The connection string has been copied to the clipboard" + ); + void vscode.window.showInformationMessage(message); } diff --git a/Source/postgres/commands/createPostgresDatabase.ts b/Source/postgres/commands/createPostgresDatabase.ts index 6c096a52b..c86e5ac45 100644 --- a/Source/postgres/commands/createPostgresDatabase.ts +++ b/Source/postgres/commands/createPostgresDatabase.ts @@ -3,24 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -import { connectPostgresDatabase } from './connectPostgresDatabase'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; +import { connectPostgresDatabase } from "./connectPostgresDatabase"; -export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); +export async function createPostgresDatabase( + context: IActionContext, + node?: PostgresServerTreeItem +): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } + const newDatabase: PostgresDatabaseTreeItem = + await node.createChild(context); + await connectPostgresDatabase(context, newDatabase); + const createMessage: string = localize( + "createPostgresDatabaseMsg", + 'Successfully created database "{0}".', + newDatabase.databaseName + ); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); } diff --git a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts index 81d54b9af..64a4fe0b5 100644 --- a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -7,6 +6,6 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; + name?: string; + query?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts index 925695e56..65288da3d 100644 --- a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts @@ -4,20 +4,31 @@ *--------------------------------------------------------------------------------------------*/ import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; +import { + postgresBaseFileName, + postgresFileExtension, +} from "../../../constants"; import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from '../../../utils/vscodeUtils'; +import * as vscodeUtil from "../../../utils/vscodeUtils"; import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; import { connectPostgresDatabase } from "../connectPostgresDatabase"; import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; -export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); +export async function runPostgresQueryWizard( + wizard: AzureWizard, + context: IPostgresQueryWizardContext, + treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem +): Promise { + await wizard.prompt(); + await wizard.execute(); + await vscodeUtil.showNewFile( + nonNullProp(context, "query"), + postgresBaseFileName, + postgresFileExtension + ); - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } + if (treeItem) { + await connectPostgresDatabase(context, treeItem.parent); + } } diff --git a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts index 9339f6796..94bb16657 100644 --- a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts @@ -6,108 +6,123 @@ import { localize } from "../../../utils/localize"; export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); + // Identifier naming rules: https://aka.ms/AA8618j + identifier = identifier.trim(); - const min = 1; - const max = 63; + const min = 1; + const max = 63; - if (identifier.length < min || identifier.length > max) { - return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } + if (identifier.length < min || identifier.length > max) { + return localize( + "postgresResourcesNameLengthCheck", + "The name must be between {0} and {1} characters.", + min, + max + ); + } - if (!identifier[0].match(/[a-z_]/i)) { - return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); - } + if (!identifier[0].match(/[a-z_]/i)) { + return localize( + "mustStartWithLetterOrUnderscore", + "Name must start with a letter or underscore." + ); + } - if (identifier.match(/[^a-z_\d$]/i)) { - return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); - } + if (identifier.match(/[^a-z_\d$]/i)) { + return localize( + "canOnlyContainCertainCharacters", + "Name can only contain letters, underscores, digits (0-9), and dollar signs ($)." + ); + } - if (reservedWords.has(identifier.toLowerCase())) { - return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); - } + if (reservedWords.has(identifier.toLowerCase())) { + return localize( + "cantBeReservedWord", + 'Name cannot be reserved word "{0}".', + identifier + ); + } - return undefined; + return undefined; } // Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html const reservedWords: Set = new Set([ - 'all', - 'analyse', - 'analyze', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'asymmetric', - 'both', - 'case', - 'cast', - 'check', - 'collate', - 'column', - 'constraint', - 'create', - 'current_catalog', - 'current_date', - 'current_role', - 'current_time', - 'current_timestamp', - 'current_user', - 'default', - 'deferrable', - 'desc', - 'distinct', - 'do', - 'else', - 'end', - 'except', - 'false', - 'fetch', - 'for', - 'foreign', - 'from', - 'grant', - 'group', - 'having', - 'in', - 'initially', - 'intersect', - 'into', - 'lateral', - 'leading', - 'limit', - 'localtime', - 'localtimestamp', - 'not', - 'null', - 'offset', - 'on', - 'only', - 'or', - 'order', - 'placing', - 'primary', - 'references', - 'returning', - 'select', - 'session_user', - 'some', - 'symmetric', - 'table', - 'then', - 'to', - 'trailing', - 'true', - 'union', - 'unique', - 'user', - 'using', - 'variadic', - 'when', - 'where', - 'window', - 'with' + "all", + "analyse", + "analyze", + "and", + "any", + "array", + "as", + "asc", + "asymmetric", + "both", + "case", + "cast", + "check", + "collate", + "column", + "constraint", + "create", + "current_catalog", + "current_date", + "current_role", + "current_time", + "current_timestamp", + "current_user", + "default", + "deferrable", + "desc", + "distinct", + "do", + "else", + "end", + "except", + "false", + "fetch", + "for", + "foreign", + "from", + "grant", + "group", + "having", + "in", + "initially", + "intersect", + "into", + "lateral", + "leading", + "limit", + "localtime", + "localtimestamp", + "not", + "null", + "offset", + "on", + "only", + "or", + "order", + "placing", + "primary", + "references", + "returning", + "select", + "session_user", + "some", + "symmetric", + "table", + "then", + "to", + "trailing", + "true", + "union", + "unique", + "user", + "using", + "variadic", + "when", + "where", + "window", + "with", ]); diff --git a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts index 390c1cf42..cc28cd581 100644 --- a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts @@ -5,20 +5,26 @@ import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; +import { + AbstractSku, + PostgresAbstractServer, + PostgresServerType, +} from "../../abstract/models"; -export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; +export interface IPostgresServerWizardContext + extends IAzureDBWizardContext, + ExecuteActivityContext { + /** + * Username without server, i.e. "user1" + */ + shortUserName?: string; + /** + * Username with server, i.e. "user1@server1" + */ + longUserName?: string; + adminPassword?: string; - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; + server?: PostgresAbstractServer; + sku?: AbstractSku; + serverType?: PostgresServerType; } diff --git a/Source/postgres/commands/deletePostgresDatabase.ts b/Source/postgres/commands/deletePostgresDatabase.ts index a09520bde..705b8823f 100644 --- a/Source/postgres/commands/deletePostgresDatabase.ts +++ b/Source/postgres/commands/deletePostgresDatabase.ts @@ -3,28 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); - const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresDatabase( + context: IActionContext, + node?: PostgresDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } + const message: string = localize( + "deletesPostgresDatabase", + 'Are you sure you want to delete database "{0}"?', + node.databaseName + ); + const result = await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresDatabase" }, + DialogResponses.deleteResponse + ); + if (result === DialogResponses.deleteResponse) { + await node.deleteTreeItem(context); + } + const deleteMessage: string = localize( + "deletePostgresDatabaseMsg", + 'Successfully deleted database "{0}".', + node.databaseName + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresFunction.ts b/Source/postgres/commands/deletePostgresFunction.ts index 9a4547428..9ee7a21d7 100644 --- a/Source/postgres/commands/deletePostgresFunction.ts +++ b/Source/postgres/commands/deletePostgresFunction.ts @@ -3,27 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } +export async function deletePostgresFunction( + context: IActionContext, + treeItem?: PostgresFunctionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresFunctionTreeItem.contextValue, + } + ); + } - const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize( + "deleteFunction", + 'Are you sure you want to delete function "{0}"?', + treeItem.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresFunction" }, + DialogResponses.deleteResponse + ); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedFunction", + 'Successfully deleted function "{0}".', + treeItem.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresServer.ts b/Source/postgres/commands/deletePostgresServer.ts index 733c6fca6..686b3c134 100644 --- a/Source/postgres/commands/deletePostgresServer.ts +++ b/Source/postgres/commands/deletePostgresServer.ts @@ -3,20 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; -import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; +import { + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { deleteDatabaseAccount } from "../../commands/deleteDatabaseAccount/deleteDatabaseAccount"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function deletePostgresServer( + context: IActionContext, + node?: PostgresServerTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - await deleteDatabaseAccount(context, node, true) + await deleteDatabaseAccount(context, node, true); } diff --git a/Source/postgres/commands/deletePostgresStoredProcedure.ts b/Source/postgres/commands/deletePostgresStoredProcedure.ts index 6abece79b..244a207d2 100644 --- a/Source/postgres/commands/deletePostgresStoredProcedure.ts +++ b/Source/postgres/commands/deletePostgresStoredProcedure.ts @@ -3,27 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; +import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } +export async function deletePostgresStoredProcedure( + context: IActionContext, + treeItem?: PostgresStoredProcedureTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = + await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresStoredProcedureTreeItem.contextValue, + } + ); + } - const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize( + "deleteStoredProcedure", + 'Are you sure you want to delete stored procedure "{0}"?', + treeItem.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresStoredProcedure" }, + DialogResponses.deleteResponse + ); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedStoredProcedure", + 'Successfully deleted stored procedure "{0}".', + treeItem.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresTable.ts b/Source/postgres/commands/deletePostgresTable.ts index bfdce33a2..60cfb0c18 100644 --- a/Source/postgres/commands/deletePostgresTable.ts +++ b/Source/postgres/commands/deletePostgresTable.ts @@ -3,26 +3,48 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; -export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); - await node.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresTable( + context: IActionContext, + node?: PostgresTableTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresTableTreeItem.contextValue, + } + ); + } + const message: string = localize( + "deletesPostgresTable", + 'Are you sure you want to delete table "{0}"?', + node.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresTable" }, + DialogResponses.deleteResponse + ); + await node.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedTable", + 'Successfully deleted table "{0}".', + node.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/enterPostgresCredentials.ts b/Source/postgres/commands/enterPostgresCredentials.ts index aa993c337..ff146d290 100644 --- a/Source/postgres/commands/enterPostgresCredentials.ts +++ b/Source/postgres/commands/enterPostgresCredentials.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { PostgresServerType } from '../abstract/models'; +import { nonNullProp } from "../../utils/nonNull"; +import { PostgresServerType } from "../abstract/models"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; import { setPostgresCredentials } from "./setPostgresCredentials"; @@ -17,69 +17,118 @@ import { setPostgresCredentials } from "./setPostgresCredentials"; * Get the username and password for the Postgres database from user input. */ async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string, password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), - stepName: 'enterPostgresUsername', - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } - }); + context: IActionContext, + serverType: PostgresServerType, + serverName: string, + serverDisplayName: string +): Promise<{ username: string; password: string }> { + let username: string = await context.ui.showInputBox({ + prompt: localize( + "enterUsername", + 'Enter username for server "{0}"', + serverDisplayName + ), + stepName: "enterPostgresUsername", + validateInput: (value: string) => { + return value && value.length + ? undefined + : localize( + "usernameCannotBeEmpty", + "Username cannot be empty." + ); + }, + }); - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { - username += usernameSuffix; - } + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexible Server instance + const usernameSuffix: string = `@${serverName}`; + if ( + serverType === PostgresServerType.Single && + !username.includes(usernameSuffix) + ) { + username += usernameSuffix; + } - const password: string = await context.ui.showInputBox({ - prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), - stepName: 'enterPostgresPassword', - password: true, - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } - }); + const password: string = await context.ui.showInputBox({ + prompt: localize( + "enterPassword", + 'Enter password for server "{0}"', + serverDisplayName + ), + stepName: "enterPostgresPassword", + password: true, + validateInput: (value: string) => { + return value && value.length + ? undefined + : localize( + "passwordCannotBeEmpty", + "Password cannot be empty." + ); + }, + }); - return { username, password }; + return { username, password }; } /** * Save the username and password in secure local storage. */ -async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { - const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; +async function persistUsernamePassword( + id: string, + serverName: string, + username: string, + password: string +): Promise { + const progressMessage: string = localize( + "setupCredentialsMessage", + 'Setting up credentials for server "{0}"...', + serverName + ); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage, + }; - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); + await vscode.window.withProgress(options, async () => { + await setPostgresCredentials(username, password, id); + }); - const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); + const completedMessage: string = localize( + "setupCredentialsMessage", + 'Successfully added credentials to server "{0}".', + serverName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); } -export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function enterPostgresCredentials( + context: IActionContext, + treeItem?: PostgresServerTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, 'azureName'); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, 'id'); + const serverType = treeItem.serverType; + const serverName: string = nonNullProp(treeItem, "azureName"); + const serverDisplayName: string = treeItem.label; + const id: string = nonNullProp(treeItem, "id"); - const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); + const { username, password } = await getUsernamePassword( + context, + serverType, + serverName, + serverDisplayName + ); - await persistUsernamePassword(id, serverName, username, password); + await persistUsernamePassword(id, serverName, username, password); - treeItem.setCredentials(username, password); - await treeItem.refresh(context); + treeItem.setCredentials(username, password); + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/executePostgresQueryInDocument.ts b/Source/postgres/commands/executePostgresQueryInDocument.ts index af5d3ca5e..4aedb847b 100644 --- a/Source/postgres/commands/executePostgresQueryInDocument.ts +++ b/Source/postgres/commands/executePostgresQueryInDocument.ts @@ -3,63 +3,92 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { EOL } from 'os'; -import * as path from 'path'; -import { ClientConfig, QueryResult } from 'pg'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import * as vscodeUtil from '../../utils/vscodeUtils'; -import { runPostgresQuery } from '../runPostgresQuery'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; -import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { EOL } from "os"; +import * as path from "path"; +import { ClientConfig, QueryResult } from "pg"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import * as vscodeUtil from "../../utils/vscodeUtils"; +import { runPostgresQuery } from "../runPostgresQuery"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { checkAuthentication } from "./checkAuthentication"; +import { loadPersistedPostgresDatabase } from "./registerPostgresCommands"; -export async function executePostgresQueryInDocument(context: IActionContext): Promise { - await loadPersistedPostgresDatabase(); +export async function executePostgresQueryInDocument( + context: IActionContext +): Promise { + await loadPersistedPostgresDatabase(); - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } + let treeItem: PostgresDatabaseTreeItem; + if (ext.connectedPostgresDB) { + treeItem = ext.connectedPostgresDB; + } else { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); + const clientConfig: ClientConfig = await checkAuthentication( + context, + treeItem + ); - const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + const activeEditor: vscode.TextEditor | undefined = + vscode.window.activeTextEditor; - if (!activeEditor?.document) { - throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); - } + if (!activeEditor?.document) { + throw new Error( + localize( + "openQueryBeforeExecuting", + "Open a PostgreSQL query before executing." + ) + ); + } - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); - ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); + const query: string | undefined = activeEditor.document.getText(); + const queryResult: QueryResult = await runPostgresQuery( + clientConfig, + query + ); + ext.outputChannel.appendLine( + localize( + "executedQuery", + 'Successfully executed "{0}" query.', + queryResult.command + ) + ); - if (queryResult.rowCount) { - const fileExtension: string = path.extname(activeEditor.document.fileName); - const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); - const outputFileName: string = `${queryFileName}-output`; + if (queryResult.rowCount) { + const fileExtension: string = path.extname( + activeEditor.document.fileName + ); + const queryFileName: string = path.basename( + activeEditor.document.fileName, + fileExtension + ); + const outputFileName: string = `${queryFileName}-output`; - const fields: string[] = queryResult.fields.map(f => f.name); - let csvData: string = `${fields.join(',')}${EOL}`; + const fields: string[] = queryResult.fields.map((f) => f.name); + let csvData: string = `${fields.join(",")}${EOL}`; - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(',')}${EOL}`; - } + for (const row of queryResult.rows) { + const fieldValues: string[] = []; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + fieldValues.push(row[field]); + } + csvData += `${fieldValues.join(",")}${EOL}`; + } - await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); - } - await treeItem.refresh(context); + await vscodeUtil.showNewFile(csvData, outputFileName, ".csv"); + } + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/openPostgresFunction.ts b/Source/postgres/commands/openPostgresFunction.ts index 26103970f..4b186ed71 100644 --- a/Source/postgres/commands/openPostgresFunction.ts +++ b/Source/postgres/commands/openPostgresFunction.ts @@ -9,13 +9,20 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } +export async function openPostgresFunction( + context: IActionContext, + treeItem?: PostgresFunctionTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresFunctionTreeItem.contextValue, + } + ); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/openPostgresStoredProcedure.ts b/Source/postgres/commands/openPostgresStoredProcedure.ts index 3c98ff743..1eb8931aa 100644 --- a/Source/postgres/commands/openPostgresStoredProcedure.ts +++ b/Source/postgres/commands/openPostgresStoredProcedure.ts @@ -9,13 +9,21 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } +export async function openPostgresStoredProcedure( + context: IActionContext, + treeItem?: PostgresStoredProcedureTreeItem +): Promise { + if (!treeItem) { + treeItem = + await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresStoredProcedureTreeItem.contextValue, + } + ); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/registerPostgresCommands.ts b/Source/postgres/commands/registerPostgresCommands.ts index b861e00f7..89412a2ba 100644 --- a/Source/postgres/commands/registerPostgresCommands.ts +++ b/Source/postgres/commands/registerPostgresCommands.ts @@ -3,10 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; import { defaults } from "pg"; import { languages } from "vscode"; -import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; +import { + connectedPostgresKey, + doubleClickDebounceDelay, + postgresDefaultDatabase, + postgresLanguageId, +} from "../../constants"; import { ext } from "../../extensionVariables"; import { openUrl } from "../../utils/openUrl"; import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; @@ -28,55 +37,126 @@ import { openPostgresFunction } from "./openPostgresFunction"; import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); + ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); + ext.context.subscriptions.push( + languages.registerCodeLensProvider( + postgresLanguageId, + ext.postgresCodeLensProvider + ) + ); - void loadPersistedPostgresDatabase(); + void loadPersistedPostgresDatabase(); - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; + //update defaults.database of 'pg' + defaults.database = postgresDefaultDatabase; - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); - registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); - registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); - registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); - registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); - registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteServer", + deletePostgresServer + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.enterCredentials", + enterPostgresCredentials + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.configureFirewall", + configurePostgresFirewall + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createDatabase", + createPostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteDatabase", + deletePostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteTable", + deletePostgresTable + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.openFunction", + openPostgresFunction, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.openStoredProcedure", + openPostgresStoredProcedure, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteFunction", + deletePostgresFunction + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteStoredProcedure", + deletePostgresStoredProcedure + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.connectDatabase", + connectPostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createFunctionQuery", + createPostgresFunctionQuery + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createStoredProcedureQuery", + createPostgresStoredProcedureQuery + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.executeQuery", + executePostgresQueryInDocument + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.copyConnectionString", + copyConnectionString + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.showPasswordlessWiki", + showPasswordlessWiki + ); } export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling( + "postgreSQL.loadPersistedDatabase", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = "true"; - try { - const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); - if (persistedTreeItem) { - await connectPostgresDatabase(context, persistedTreeItem); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); + try { + const persistedTreeItemId: string | undefined = + ext.context.globalState.get(connectedPostgresKey); + if (persistedTreeItemId) { + const persistedTreeItem: + | PostgresDatabaseTreeItem + | undefined = ( + await ext.rgApi.appResourceTree.findTreeItem( + persistedTreeItemId, + context + ) + ); + if (persistedTreeItem) { + await connectPostgresDatabase( + context, + persistedTreeItem + ); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase( + undefined + ); + } + } + } + ); } export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); + await openUrl("https://aka.ms/postgresql-passwordless-wiki"); } diff --git a/Source/postgres/commands/setPostgresCredentials.ts b/Source/postgres/commands/setPostgresCredentials.ts index 8df8260f6..2807acc3c 100644 --- a/Source/postgres/commands/setPostgresCredentials.ts +++ b/Source/postgres/commands/setPostgresCredentials.ts @@ -8,25 +8,37 @@ import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } -export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; +export async function setPostgresCredentials( + username: string, + password: string, + serverId: string +): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = + ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue + ? JSON.parse(storedValue) + : []; - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); + // Remove this server from the cache if it's there + servers = servers.filter((server: IPersistedServer) => { + return server.id !== serverId; + }); - const newServer: IPersistedServer = { - id: serverId, - username - }; + const newServer: IPersistedServer = { + id: serverId, + username, + }; - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); + servers.push(newServer); + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.store( + getSecretStorageKey(serviceName, serverId), + password + ); } diff --git a/Source/postgres/getClientConfig.ts b/Source/postgres/getClientConfig.ts index bdc545945..431a95bea 100644 --- a/Source/postgres/getClientConfig.ts +++ b/Source/postgres/getClientConfig.ts @@ -8,12 +8,15 @@ import { ConnectionOptions } from "tls"; import { postgresDefaultPort } from "../constants"; import { nonNullProp } from "../utils/nonNull"; import { PostgresServerType } from "./abstract/models"; -import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; +import { + ParsedPostgresConnectionString, + addDatabaseToConnectionString, +} from "./postgresConnectionStrings"; export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; + password: ClientConfig | undefined; + azureAd: ClientConfig | undefined; + connectionString: ClientConfig | undefined; }; export type PostgresClientConfigType = keyof PostgresClientConfigs; @@ -21,82 +24,133 @@ export type PostgresClientConfigType = keyof PostgresClientConfigs; * Test if the database can be connected to using the given client config. * @throws if the client failed to connect to the database. */ -export async function testClientConfig(clientConfig: ClientConfig): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } +export async function testClientConfig( + clientConfig: ClientConfig +): Promise { + const client = new Client(clientConfig); + try { + await client.connect(); + } finally { + await client.end(); + } } -async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString(connectionString, databaseName); - } - return { connectionString: connectionString }; +async function getConnectionStringClientConfig( + parsedConnectionString: ParsedPostgresConnectionString, + databaseName: string +): Promise { + let connectionString = parsedConnectionString.connectionString; + if (!parsedConnectionString.databaseName) { + connectionString = addDatabaseToConnectionString( + connectionString, + databaseName + ); + } + return { connectionString: connectionString }; } -async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; +async function getUsernamePasswordClientConfig( + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string +): Promise { + const host = nonNullProp(parsedConnectionString, "hostName"); + const port: number = parsedConnectionString.port + ? parseInt(parsedConnectionString.port) + : parseInt(postgresDefaultPort); + const username: string | undefined = parsedConnectionString.username; + const password: string | undefined = parsedConnectionString.password; - if (!!username && !!password && !!host && !!port) { - return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; - } else { - return undefined; - } + if (!!username && !!password && !!host && !!port) { + return { + user: username, + password, + ssl: sslAzure, + host, + port, + database: databaseName, + }; + } else { + return undefined; + } } async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string, + azureAdUserId: string, + getToken: () => Promise ): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; + const host = nonNullProp(parsedConnectionString, "hostName"); + const port: number = parsedConnectionString.port + ? parseInt(parsedConnectionString.port) + : parseInt(postgresDefaultPort); + return { + user: azureAdUserId, + password: getToken, + ssl: sslAzure, + host, + port, + database: databaseName, + }; } export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + serverType: PostgresServerType, + hasSubscription: boolean, + databaseName: string, + azureUserId?: string, + getToken?: () => Promise ): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] - }; - const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { - const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); - clientConfigs.connectionString = connectionStringClientConfig; - } + const clientConfigs: PostgresClientConfigs = { + password: undefined, + azureAd: undefined, + connectionString: undefined, + }; + if (hasSubscription) { + const sslAzure: ConnectionOptions = { + // Always provide the certificate since it is accepted even when SSL is disabled + // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) + // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 + ca: + serverType === PostgresServerType.Single + ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] + : [DigiCertGlobalRootCA], + }; + const passwordClientConfig = await getUsernamePasswordClientConfig( + parsedConnectionString, + sslAzure, + databaseName + ); + if (passwordClientConfig) { + clientConfigs.password = passwordClientConfig; + } + if ( + serverType === PostgresServerType.Flexible && + !!azureUserId && + !!getToken + ) { + const azureAdClientConfig = await getAzureAdClientConfig( + parsedConnectionString, + sslAzure, + databaseName, + azureUserId, + getToken + ); + clientConfigs.azureAd = azureAdClientConfig; + } + } else { + const connectionStringClientConfig = + await getConnectionStringClientConfig( + parsedConnectionString, + databaseName + ); + clientConfigs.connectionString = connectionStringClientConfig; + } - return clientConfigs; + return clientConfigs; } // Postgres Single Server Root Cert, https://aka.ms/AA7wnvl @@ -169,4 +223,3 @@ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE-----`; - diff --git a/Source/postgres/getPostgresProcedureQueryRows.ts b/Source/postgres/getPostgresProcedureQueryRows.ts index ad791ff2e..0cecca979 100644 --- a/Source/postgres/getPostgresProcedureQueryRows.ts +++ b/Source/postgres/getPostgresProcedureQueryRows.ts @@ -9,16 +9,16 @@ import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; + schema: string; + name: string; + oid: number; + args: string; + definition: string; } function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, + // Adapted from https://aka.ms/AA83fg8 + return `select n.nspname as schema, p.proname as name, p.oid as oid, pg_get_function_arguments(p.oid) as args, @@ -33,26 +33,37 @@ function getProceduresQuery(conditions: string): string { order by name;`; } -export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { - let conditions: string; +export async function getPostgresProcedureQueryRows( + treeItem: PostgresResourcesTreeItemBase +): Promise { + let conditions: string; - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } + if (treeItem instanceof PostgresFunctionsTreeItem) { + conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') + ${ + (await treeItem.parent.parent.supportsStoredProcedures( + treeItem.clientConfig + )) + ? "and p.prokind = 'f'" + : "" + }`; + } else { + // Assume stored procedures + conditions = "and p.prokind = 'p'"; + } - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; + const query: string = getProceduresQuery(conditions); + const queryResult: QueryResult = await runPostgresQuery( + treeItem.clientConfig, + query + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } + treeItem.resourcesAndSchemas = {}; + for (const row of rows) { + treeItem.addResourcesAndSchemasEntry(row.name, row.schema); + } - return rows; + return rows; } diff --git a/Source/postgres/getTables.ts b/Source/postgres/getTables.ts index ebc7d1c75..e74d1074d 100644 --- a/Source/postgres/getTables.ts +++ b/Source/postgres/getTables.ts @@ -7,10 +7,10 @@ import { ClientConfig, QueryResult } from "pg"; import { runPostgresQuery } from "./runPostgresQuery"; export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; + schemaName: string; + name: string; + oid: string; + columnNames: string[]; } const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, @@ -23,12 +23,22 @@ const tablesQuery: string = `select schemaname, tablename, array_agg (columnname where schemaname != 'pg_catalog' AND schemaname != 'information_schema' group by schemaname, tablename;`; -export async function getTables(clientConfig: ClientConfig): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); - } - return tablesArray; +export async function getTables( + clientConfig: ClientConfig +): Promise { + const tableInfoRows: QueryResult = await runPostgresQuery( + clientConfig, + tablesQuery + ); + const tablesArray: IPostgresTable[] = []; + for (const row of tableInfoRows.rows) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + tablesArray.push({ + schemaName: row.schemaname, + name: row.tablename, + oid: row.oid, + columnNames: row.columnnames, + }); + } + return tablesArray; } diff --git a/Source/postgres/postgresConnectionStrings.ts b/Source/postgres/postgresConnectionStrings.ts index ea9ce9e2e..f1c46e6e7 100644 --- a/Source/postgres/postgresConnectionStrings.ts +++ b/Source/postgres/postgresConnectionStrings.ts @@ -8,67 +8,84 @@ import { postgresDefaultPort } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; import { nonNullProp } from "../utils/nonNull"; -export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); +export function parsePostgresConnectionString( + connectionString: string +): ParsedPostgresConnectionString { + const config: ConnectionOptions = parse(connectionString.trim()); + return new ParsedPostgresConnectionString(connectionString, config); } -export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); +export function addDatabaseToConnectionString( + connectionString: string, + databaseName: string +): string { + const url = new URL(connectionString); + url.pathname = encodeURIComponent(databaseName); + return url.toString(); } -export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function createPostgresConnectionString( + hostName: string, + port: string = postgresDefaultPort, + username?: string | undefined, + password?: string | undefined, + databaseName?: string | undefined +): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + connectionString += `${encodedUsername}:${encodedPassword}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } -export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function copyPostgresConnectionString( + hostName: string, + port: string = postgresDefaultPort, + username?: string | undefined, + password?: string | undefined, + databaseName?: string | undefined +): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; + connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; + public readonly hostName: string; + public username: string | undefined; + public password: string | undefined; + public readonly port: string; - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, 'host'); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } + constructor(connectionString: string, config: ConnectionOptions) { + super(connectionString, config.database ? config.database : undefined); + this.hostName = nonNullProp(config, "host"); + this.port = config.port ? config.port : `${postgresDefaultPort}`; + this.username = config.user; + this.password = config.password; + } } diff --git a/Source/postgres/postgresConstants.ts b/Source/postgres/postgresConstants.ts index 9bcf15144..f94f58a25 100644 --- a/Source/postgres/postgresConstants.ts +++ b/Source/postgres/postgresConstants.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const invalidCredentialsErrorType: string = '28P01'; -export const firewallNotConfiguredErrorType: string = '28000'; -export const timeoutErrorType = 'ETIMEDOUT'; +export const invalidCredentialsErrorType: string = "28P01"; +export const firewallNotConfiguredErrorType: string = "28000"; +export const timeoutErrorType = "ETIMEDOUT"; diff --git a/Source/postgres/runPostgresQuery.ts b/Source/postgres/runPostgresQuery.ts index b7d325364..ce2a67c7b 100644 --- a/Source/postgres/runPostgresQuery.ts +++ b/Source/postgres/runPostgresQuery.ts @@ -5,15 +5,18 @@ import { Client, ClientConfig, QueryResult } from "pg"; -export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } +export async function runPostgresQuery( + clientConfig: ClientConfig, + query: string +): Promise { + const client: Client = new Client(clientConfig); + try { + await client.connect(); + return await client.query(query); + } finally { + await client.end(); + } } export function wrapArgInQuotes(input: string): string { - return `"${input}"`; + return `"${input}"`; } diff --git a/Source/postgres/services/PostgresCodeLensProvider.ts b/Source/postgres/services/PostgresCodeLensProvider.ts index 5d075eb3c..d0d6bfe39 100644 --- a/Source/postgres/services/PostgresCodeLensProvider.ts +++ b/Source/postgres/services/PostgresCodeLensProvider.ts @@ -3,64 +3,88 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { + CodeLens, + CodeLensProvider, + Event, + EventEmitter, + Position, + ProviderResult, + Range, +} from "vscode"; import { localize } from "../../utils/localize"; export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: EventEmitter = new EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(): ProviderResult { + return callWithTelemetryAndErrorHandling( + "postgreSQL.provideCodeLenses", + (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: CodeLens[] = []; - let title: string; - if (!isInitialized) { - title = localize('initializing', 'Initializing...'); - } else if (isConnected) { - title = localize('connectedToDatabase', 'Connected to "{0}"', database); - } else { - title = localize('connectToDatabase', 'Connect to a database'); - } + let title: string; + if (!isInitialized) { + title = localize("initializing", "Initializing..."); + } else if (isConnected) { + title = localize( + "connectedToDatabase", + 'Connected to "{0}"', + database + ); + } else { + title = localize( + "connectToDatabase", + "Connect to a database" + ); + } - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && 'postgreSQL.connectDatabase' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title, + command: isInitialized && "postgreSQL.connectDatabase", + }, + range: new Range(new Position(0, 0), new Position(0, 0)), + }); - if (isConnected) { - lenses.push({ - command: { - title: 'Execute Query', - command: 'postgreSQL.executeQuery' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - } + if (isConnected) { + lenses.push({ + command: { + title: "Execute Query", + command: "postgreSQL.executeQuery", + }, + range: new Range( + new Position(0, 0), + new Position(0, 0) + ), + }); + } - return lenses; - }); - } + return lenses; + } + ); + } } diff --git a/Source/postgres/showPostgresQuery.ts b/Source/postgres/showPostgresQuery.ts index 7d6e2aa1d..4d1b277b4 100644 --- a/Source/postgres/showPostgresQuery.ts +++ b/Source/postgres/showPostgresQuery.ts @@ -3,12 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { postgresBaseFileName, postgresFileExtension } from '../constants'; -import * as vscodeUtil from '../utils/vscodeUtils'; +import { postgresBaseFileName, postgresFileExtension } from "../constants"; +import * as vscodeUtil from "../utils/vscodeUtils"; import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; -export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); +export async function showPostgresQuery( + treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem +): Promise { + const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; + await vscodeUtil.showNewFile( + treeItem.definition, + fileName, + postgresFileExtension + ); } diff --git a/Source/postgres/tree/ClientConfigFactory.ts b/Source/postgres/tree/ClientConfigFactory.ts index 271f5b92f..67a00710c 100644 --- a/Source/postgres/tree/ClientConfigFactory.ts +++ b/Source/postgres/tree/ClientConfigFactory.ts @@ -3,84 +3,123 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + parseError, +} from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; +import { + getAzureAdUserSession, + getTokenFunction, +} from "../../azureAccountUtils"; import { localize } from "../../utils/localize"; -import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; +import { + PostgresClientConfigType, + getClientConfigs, + testClientConfig, +} from "../getClientConfig"; +import { + firewallNotConfiguredErrorType, + invalidCredentialsErrorType, + timeoutErrorType, +} from "../postgresConstants"; import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; +export const postgresResourceType = + "https://ossrdbms-aad.database.windows.net/"; /** * Creates an object that can be used to execute a postgres query with connection test and telemetry. */ export class PostgresClientConfigFactory { - public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ - type: "azureAd" | "password" | "connectionString", - clientConfig: ClientConfig - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); + public static async getClientConfigFromNode( + treeItem: PostgresServerTreeItem, + databaseName: string + ): Promise<{ + type: "azureAd" | "password" | "connectionString"; + clientConfig: ClientConfig; + }> { + const parsedConnectionString = await treeItem.getFullConnectionString(); + const azureUserSession = await getAzureAdUserSession(); - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); + let hasSubscription: boolean = false; + let tokenFunction: (() => Promise) | undefined = undefined; + try { + const subscription = treeItem.subscription; + hasSubscription = true; + tokenFunction = getTokenFunction( + subscription.credentials, + postgresResourceType + ); + } catch (error) { + hasSubscription = false; + } + const clientConfigs = await getClientConfigs( + parsedConnectionString, + treeItem.serverType, + hasSubscription, + databaseName, + azureUserSession?.userId, + tokenFunction + ); - const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; + const clientConfigTypeOrder: PostgresClientConfigType[] = [ + "azureAd", + "password", + "connectionString", + ]; - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } + for (const clientConfigType of clientConfigTypeOrder) { + const clientConfig: ClientConfig | undefined = + clientConfigs[clientConfigType]; + if (!clientConfig) { + continue; + } - try { - await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = clientConfigType; - await testClientConfig(clientConfig); - }); - return { - type: clientConfigType, - clientConfig - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), - code: firewallNotConfiguredErrorType - }; - } else { - throw error; - } - } - } + try { + await callWithTelemetryAndErrorHandling( + "postgreSQL.testClientConfig", + async (context) => { + context.errorHandling.rethrow = true; + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.clientConfigType = + clientConfigType; + await testClientConfig(clientConfig); + } + ); + return { + type: clientConfigType, + clientConfig, + }; + } catch (error) { + const parsedError = parseError(error); + if (parsedError.errorType === invalidCredentialsErrorType) { + // If the client config failed with invalid credential error, skip and try the next available one. + } else if ( + parsedError.errorType === firewallNotConfiguredErrorType || + parsedError.errorType === timeoutErrorType + ) { + // The time out error are common when the firewall rules doesn't grant access from the current IP address. + // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. + throw { + message: localize( + "mustConfigureFirewall", + "Must configure firewall from Azure Portal to grant access." + ), + code: firewallNotConfiguredErrorType, + }; + } else { + throw error; + } + } + } - throw { - message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), - code: invalidCredentialsErrorType - }; - } + throw { + message: localize( + "mustEnterCredentials", + "Must enter credentials to connect to server." + ), + code: invalidCredentialsErrorType, + }; + } } diff --git a/Source/postgres/tree/PostgresColumnTreeItem.ts b/Source/postgres/tree/PostgresColumnTreeItem.ts index d284c8122..aedfa46f2 100644 --- a/Source/postgres/tree/PostgresColumnTreeItem.ts +++ b/Source/postgres/tree/PostgresColumnTreeItem.ts @@ -3,31 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; +import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; + public static contextValue: string = "postgresColumn"; + public readonly contextValue: string = PostgresColumnTreeItem.contextValue; + public readonly columnName: string; + public readonly parent: PostgresTableTreeItem; - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } + constructor(parent: PostgresTableTreeItem, columnName: string) { + super(parent); + this.columnName = columnName; + } - public get id(): string { - return this.columnName; - } + public get id(): string { + return this.columnName; + } - public get label(): string { - return this.columnName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('split-horizontal'); - } + public get label(): string { + return this.columnName; + } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("split-horizontal"); + } } diff --git a/Source/postgres/tree/PostgresDatabaseTreeItem.ts b/Source/postgres/tree/PostgresDatabaseTreeItem.ts index 05f7a4412..e9463d0bc 100644 --- a/Source/postgres/tree/PostgresDatabaseTreeItem.ts +++ b/Source/postgres/tree/PostgresDatabaseTreeItem.ts @@ -4,112 +4,178 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line import/no-internal-modules -import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { ThemeIcon } from 'vscode'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresServerTreeItem } from './PostgresServerTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import { + AzExtParentTreeItem, + AzExtTreeItem, + createContextValue, + GenericTreeItem, + IActionContext, + IParsedError, + parseError, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { ThemeIcon } from "vscode"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { + firewallNotConfiguredErrorType, + invalidCredentialsErrorType, +} from "../postgresConstants"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresClientConfigFactory } from "./ClientConfigFactory"; +import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; +import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; +import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; + public static contextValue: string = "postgresDatabase"; + public contextValue: string = PostgresDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Resource Type"; + public readonly databaseName: string; + public readonly parent: PostgresServerTreeItem; + public autoSelectInTreeItemPicker: boolean = true; + public isShowingPasswordWarning: boolean; - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } + constructor(parent: PostgresServerTreeItem, databaseName: string) { + super(parent); + this.databaseName = databaseName; + this.isShowingPasswordWarning = false; + } - public get label(): string { - return this.databaseName; - } + public get label(): string { + return this.databaseName; + } - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; - } + public get description(): string { + return ext.connectedPostgresDB?.fullId === this.fullId + ? localize("connected", "Connected") + : ""; + } - public get id(): string { - return this.databaseName; - } + public get id(): string { + return this.databaseName; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('database'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("database"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresFirewall', - label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.configureFirewall' - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: "postgresFirewall", + label: localize( + "configureFirewall", + 'Configure firewall to connect to "{0}"...', + this.parent.label + ), + commandId: "postgreSQL.configureFirewall", + }); + firewallTreeItem.commandArgs = [this.parent]; + return [firewallTreeItem]; + } - try { - const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig) - ]; + try { + const { type, clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this.parent, + this.databaseName + ); + if (type === "password") { + void this.showPasswordWarning(context); + } + const children: AzExtTreeItem[] = [ + new PostgresFunctionsTreeItem(this, clientConfig), + new PostgresTablesTreeItem(this, clientConfig), + ]; - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); - } + if (await this.parent.supportsStoredProcedures(clientConfig)) { + children.push( + new PostgresStoredProceduresTreeItem(this, clientConfig) + ); + } - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); + return children; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresCredentials', - label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.enterCredentials' - }); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - return []; - } else { - throw error; - } - } - } + if ( + this.parent.azureName && + parsedError.errorType === invalidCredentialsErrorType + ) { + void context.ui.showWarningMessage( + localize( + "couldNotConnect", + 'Could not connect to "{0}": {1}', + this.parent.label, + parsedError.message + ), + { stepName: "loadPostgresDatabases" } + ); + const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem( + this, + { + contextValue: "postgresCredentials", + label: localize( + "enterCredentials", + 'Enter server credentials to connect to "{0}"...', + this.parent.label + ), + commandId: "postgreSQL.enterCredentials", + } + ); + credentialsTreeItem.commandArgs = [this.parent]; + return [credentialsTreeItem]; + } else if ( + this.parent.azureName && + parsedError.errorType === firewallNotConfiguredErrorType + ) { + void context.ui.showWarningMessage( + localize( + "couldNotConnect", + 'Could not connect to "{0}": {1}', + this.parent.label, + parsedError.message + ), + { stepName: "loadPostgresDatabases" } + ); + return []; + } else { + throw error; + } + } + } - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); - } + public async deleteTreeItemImpl(): Promise { + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this.parent, + this.databaseName + ); + await runPostgresQuery( + clientConfig, + `Drop Database ${wrapArgInQuotes(this.databaseName)};` + ); + } - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); - await this.refresh(context); - } + private async showPasswordWarning(context: IActionContext): Promise { + if (this.isShowingPasswordWarning) { + return; + } + this.isShowingPasswordWarning = true; + this.contextValue = createContextValue([ + PostgresDatabaseTreeItem.contextValue, + "usesPassword", + ]); + await this.refresh(context); + } } diff --git a/Source/postgres/tree/PostgresFunctionTreeItem.ts b/Source/postgres/tree/PostgresFunctionTreeItem.ts index 0a26bf3f9..d7bc46a16 100644 --- a/Source/postgres/tree/PostgresFunctionTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionTreeItem.ts @@ -10,39 +10,49 @@ import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresFunction'; - public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = "postgresFunction"; + public readonly contextValue: string = + PostgresFunctionTreeItem.contextValue; + public readonly parent: PostgresFunctionsTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openFunction'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor( + parent: PostgresFunctionsTreeItem, + row: IPostgresProceduresQueryRow, + isDuplicate: boolean + ) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = "postgreSQL.openFunction"; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("symbol-function"); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${ + this.args + });` + ); + } } diff --git a/Source/postgres/tree/PostgresFunctionsTreeItem.ts b/Source/postgres/tree/PostgresFunctionsTreeItem.ts index 7d3904e83..8f373ab95 100644 --- a/Source/postgres/tree/PostgresFunctionsTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionsTreeItem.ts @@ -4,43 +4,51 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { ClientConfig } from "pg"; +import { ThemeIcon } from "vscode"; +import { + getPostgresProcedureQueryRows, + IPostgresProceduresQueryRow, +} from "../getPostgresProcedureQueryRows"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; +import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresFunctions'; - public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; - public readonly label: string = 'Functions'; - public readonly childTypeLabel: string = 'Function'; - public suppressMaskLabel = true; + public static contextValue: string = "postgresFunctions"; + public readonly contextValue: string = + PostgresFunctionsTreeItem.contextValue; + public readonly label: string = "Functions"; + public readonly childTypeLabel: string = "Function"; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("symbol-function"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = + await getPostgresProcedureQueryRows(this); + return rows.map( + (row) => + new PostgresFunctionTreeItem( + this, + row, + this.isDuplicateResource(row.name) + ) + ); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresFunctionTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts index b93cc9450..40e4d07c5 100644 --- a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts +++ b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts @@ -9,19 +9,19 @@ import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; // Base class for Postgres tree items whose children are individual resources export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas + public parent: PostgresDatabaseTreeItem; + public clientConfig: ClientConfig; + public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } + public addResourcesAndSchemasEntry(name: string, schema: string): void { + if (this.resourcesAndSchemas[name]) { + this.resourcesAndSchemas[name].push(schema); + } else { + this.resourcesAndSchemas[name] = [schema]; + } + } - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } + public isDuplicateResource(name: string): boolean { + return this.resourcesAndSchemas[name].length > 1; + } } diff --git a/Source/postgres/tree/PostgresServerTreeItem.ts b/Source/postgres/tree/PostgresServerTreeItem.ts index 20e7dbe76..1ffc11403 100644 --- a/Source/postgres/tree/PostgresServerTreeItem.ts +++ b/Source/postgres/tree/PostgresServerTreeItem.ts @@ -3,250 +3,383 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from '@azure/arm-postgresql'; -import * as FlexibleModels from '@azure/arm-postgresql-flexible'; -import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import { ClientConfig } from 'pg'; -import { SemVer, coerce, gte } from 'semver'; -import * as vscode from 'vscode'; -import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { isIpInRanges } from '../../utils/getIp'; -import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; -import { getPublicIp } from '../commands/configurePostgresFirewall'; -import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import * as SingleModels from "@azure/arm-postgresql"; +import * as FlexibleModels from "@azure/arm-postgresql-flexible"; +import { + getResourceGroupFromId, + parseAzureResourceId, + uiUtils, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + IActionContext, + ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import { ClientConfig } from "pg"; +import { SemVer, coerce, gte } from "semver"; +import * as vscode from "vscode"; +import { + getThemeAgnosticIconPath, + postgresDefaultDatabase, +} from "../../constants"; +import { ext } from "../../extensionVariables"; +import { isIpInRanges } from "../../utils/getIp"; +import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../abstract/AbstractPostgresClient"; +import { PostgresAbstractServer, PostgresServerType } from "../abstract/models"; +import { getPublicIp } from "../commands/configurePostgresFirewall"; +import { ParsedPostgresConnectionString } from "../postgresConnectionStrings"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresClientConfigFactory } from "./ClientConfigFactory"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; +import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; +import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; +import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; +import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; - } - this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('PostgresServer.svg'); - } - - public get label(): string { - return this.azureName ? this.azureName : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); - dbNames = listOfDatabases.map(db => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map(db => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - 'invalidPostgresServer', - dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, - dbName => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); - } - const getChildrenTask: Promise = this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createPostgresDatabase', - validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) - }); - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, '11.0.0'); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); - - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); - } - - public async getFullConnectionString(): Promise { - - if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { - const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp(this, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); - const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } + public static contextValue: string = "postgresServer"; + public static serviceName: string = + "ms-azuretools.vscode-azuredatabases.postgresPasswords"; + public readonly contextValue: string = PostgresServerTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly serverType: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + constructor( + parent: AzExtParentTreeItem, + connectionString: ParsedPostgresConnectionString, + server?: PostgresAbstractServer + ) { + super(parent); + this.partialConnectionString = connectionString; + if (server) { + this.azureId = server?.id; + this.serverVersion = server?.version; + this.resourceGroup = getResourceGroupFromId(this.fullId); + this.azureName = server?.name; + this.serverType = parseAzureResourceId(this.fullId) + .provider.toLowerCase() + .includes("flexible") + ? PostgresServerType.Flexible + : PostgresServerType.Single; + } + this.valuesToMask.push( + connectionString.accountId, + connectionString.connectionString, + connectionString.fullId, + connectionString.hostName, + connectionString.port + ); + if (connectionString.databaseName) { + this.valuesToMask.push(connectionString.databaseName); + } + } + + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("PostgresServer.svg"); + } + + public get label(): string { + return this.azureName + ? this.azureName + : this.partialConnectionString.fullId; + } + + public get id(): string { + if (this.azureId) { + return this.azureId; + } + return this.partialConnectionString.fullId; + } + + public get description(): string | undefined { + switch (this.serverType) { + case PostgresServerType.Flexible: + return "PostgreSQL Flexible"; + case PostgresServerType.Single: + return "PostgreSQL Single"; + default: + return "PostgreSQL"; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + context.telemetry.properties.serverType = this.serverType; + let dbNames: (string | undefined)[]; + if (this.azureName) { + const client: AbstractPostgresClient = + await createAbstractPostgresClient(this.serverType, [ + context, + this.subscription, + ]); + const listOfDatabases: ( + | SingleModels.Database + | FlexibleModels.Database + )[] = await uiUtils.listAllIterator( + client.databases.listByServer( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ) + ); + dbNames = listOfDatabases.map((db) => db.name); + } else if (this.partialConnectionString.databaseName) { + dbNames = [this.partialConnectionString.databaseName]; + } else { + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this, + postgresDefaultDatabase + ); + const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; + const queryResult = await runPostgresQuery(clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + dbNames = queryResult.rows.map((db) => db?.datname); + } + + return this.createTreeItemsWithErrorHandling( + dbNames, + "invalidPostgresServer", + (dbName) => + dbName && !["azure_maintenance", "azure_sys"].includes(dbName) + ? new PostgresDatabaseTreeItem(this, dbName) + : undefined, + (dbName) => dbName + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case PostgresDatabaseTreeItem.contextValue: + case PostgresTablesTreeItem.contextValue: + case PostgresTableTreeItem.contextValue: + case PostgresFunctionsTreeItem.contextValue: + case PostgresFunctionTreeItem.contextValue: + case PostgresStoredProceduresTreeItem.contextValue: + case PostgresStoredProcedureTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + if (this.partialConnectionString.databaseName) { + throw new Error( + localize( + "noPermissionToCreateDatabase", + `This attached account does not have permissions to create a database.` + ) + ); + } + const getChildrenTask: Promise = + this.getCachedChildren(context); + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: "createPostgresDatabase", + validateInput: (name: string) => + validateDatabaseName(name, getChildrenTask), + }); + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this, + databaseName + ); + context.showCreatingTreeItem(databaseName); + await runPostgresQuery( + clientConfig, + `Create Database ${wrapArgInQuotes(databaseName)};` + ); + return new PostgresDatabaseTreeItem(this, databaseName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const client = await createAbstractPostgresClient(this.serverType, [ + context, + this.subscription, + ]); + const deletingMessage: string = `Deleting server "${this.label}"...`; + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: deletingMessage, + }, + async () => { + await client.servers.beginDeleteAndWait( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ); + await this.deletePostgresCredentials(); + + const deleteMessage: string = localize( + "deleteServerMsg", + 'Successfully deleted server "{0}".', + this.label + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + } + ); + } + + public setCredentials(username: string, password: string): void { + this.partialConnectionString.username = username; + this.partialConnectionString.password = password; + } + + public async supportsStoredProcedures( + clientConfig: ClientConfig + ): Promise { + // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer + if (!this.serverVersion) { + const result = await runPostgresQuery( + clientConfig, + `SHOW server_version;` + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + this.serverVersion = result.rows[0].server_version; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + const version: SemVer | null = coerce(this.serverVersion); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call + return gte(version, "11.0.0"); + } + + public async deletePostgresCredentials(): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = + ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue + ? JSON.parse(storedValue) + : []; + + // Remove this server from the cache + servers = servers.filter((server: IPersistedServer) => { + return server.id !== this.id; + }); + + await ext.context.globalState.update( + serviceName, + JSON.stringify(servers) + ); + await ext.secretStorage.delete( + getSecretStorageKey(serviceName, this.id) + ); + } + + public async getFullConnectionString(): Promise { + if ( + this.azureId && + !( + this.partialConnectionString.username && + this.partialConnectionString.password + ) + ) { + const storedValue: string | undefined = ext.context.globalState.get( + PostgresServerTreeItem.serviceName + ); + if (storedValue) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const servers: IPersistedServer[] = JSON.parse(storedValue); + for (const server of servers) { + if (server.id === this.id) { + this.partialConnectionString.username = server.username; + // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials + this.partialConnectionString.password = + (await ext.secretStorage.get( + getSecretStorageKey( + PostgresServerTreeItem.serviceName, + this.id + ) + )) || undefined; + break; + } + } + } + } + return this.partialConnectionString; + } + + /** + * @returns true if we believe the firewall allows the current IP to connect to database server. + */ + public async isFirewallRuleSet(context: IActionContext): Promise { + try { + const serverType: PostgresServerType = nonNullProp( + this, + "serverType" + ); + const client: AbstractPostgresClient = + await createAbstractPostgresClient(serverType, [ + context, + this.subscription, + ]); + const results: SingleModels.FirewallRule[] = + await uiUtils.listAllIterator( + client.firewallRules.listByServer( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ) + ); + const publicIp: string = await getPublicIp(context); + return isIpInRanges(publicIp, results); + } catch (error) { + // We cannot get the firewall rules from attached databases because we cannot get the subscription object. + // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. + return true; + } + } } -async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { - if (!name) { - return localize('NameCannotBeEmpty', 'Name cannot be empty.'); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize('NameExists', 'Database "{0}" already exists.', name); - } - return undefined; +async function validateDatabaseName( + name: string, + getChildrenTask: Promise +): Promise { + if (!name) { + return localize("NameCannotBeEmpty", "Name cannot be empty."); + } + const currDatabaseList = await getChildrenTask; + const currDatabaseNames: string[] = []; + for (const db of currDatabaseList) { + if (db instanceof PostgresDatabaseTreeItem) { + currDatabaseNames.push(db.databaseName); + } + } + if (currDatabaseNames.includes(name)) { + return localize("NameExists", 'Database "{0}" already exists.', name); + } + return undefined; } diff --git a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts index 503d0ae74..1c903d9e2 100644 --- a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts @@ -10,39 +10,47 @@ import { runPostgresQuery } from "../runPostgresQuery"; import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresStoredProcedure'; - public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = "postgresStoredProcedure"; + public readonly contextValue: string = + PostgresStoredProcedureTreeItem.contextValue; + public readonly parent: PostgresStoredProceduresTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openStoredProcedure'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor( + parent: PostgresStoredProceduresTreeItem, + row: IPostgresProceduresQueryRow, + isDuplicate: boolean + ) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = "postgreSQL.openStoredProcedure"; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("server-process"); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});` + ); + } } diff --git a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts index 1c516e00f..9525856f6 100644 --- a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts @@ -4,43 +4,53 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; +import { ClientConfig } from "pg"; +import { ThemeIcon } from "vscode"; +import { + getPostgresProcedureQueryRows, + IPostgresProceduresQueryRow, +} from "../getPostgresProcedureQueryRows"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; +import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresStoredProcedures'; - public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = 'Stored Procedures'; - public readonly childTypeLabel: string = 'Stored Procedure'; - public suppressMaskLabel = true; + public static contextValue: string = "postgresStoredProcedures"; + public readonly contextValue: string = + PostgresStoredProceduresTreeItem.contextValue; + public readonly label: string = "Stored Procedures"; + public readonly childTypeLabel: string = "Stored Procedure"; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("server-process"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } + public async loadMoreChildrenImpl(): Promise< + PostgresStoredProcedureTreeItem[] + > { + const rows: IPostgresProceduresQueryRow[] = + await getPostgresProcedureQueryRows(this); + return rows.map( + (row) => + new PostgresStoredProcedureTreeItem( + this, + row, + this.isDuplicateResource(row.name) + ) + ); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresStoredProcedureTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresTableTreeItem.ts b/Source/postgres/tree/PostgresTableTreeItem.ts index ef5d87c2c..fb844038b 100644 --- a/Source/postgres/tree/PostgresTableTreeItem.ts +++ b/Source/postgres/tree/PostgresTableTreeItem.ts @@ -3,54 +3,68 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IPostgresTable } from '../getTables'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import { + AzExtParentTreeItem, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IPostgresTable } from "../getTables"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresColumnTreeItem } from "./PostgresColumnTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; + public static contextValue: string = "postgresTable"; + public readonly contextValue: string = PostgresTableTreeItem.contextValue; + public readonly table: IPostgresTable; + public readonly parent: PostgresTablesTreeItem; - private _isDuplicate: boolean; + private _isDuplicate: boolean; - constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } + constructor( + parent: PostgresTablesTreeItem, + table: IPostgresTable, + isDuplicate: boolean + ) { + super(parent); + this.table = table; + this._isDuplicate = isDuplicate; + } - public get id(): string { - return String(this.table.oid); - } + public get id(): string { + return String(this.table.oid); + } - public get label(): string { - return this.table.name; - } + public get label(): string { + return this.table.name; + } - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } + public get description(): string | undefined { + return this._isDuplicate ? this.table.schemaName : undefined; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('window'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("window"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); - } + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return this.table.columnNames.map( + (columnName) => new PostgresColumnTreeItem(this, columnName) + ); + } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `Drop Table ${this.table.schemaName}.${wrapArgInQuotes( + this.table.name + )};` + ); + } } diff --git a/Source/postgres/tree/PostgresTablesTreeItem.ts b/Source/postgres/tree/PostgresTablesTreeItem.ts index c18c065db..4c15ef812 100644 --- a/Source/postgres/tree/PostgresTablesTreeItem.ts +++ b/Source/postgres/tree/PostgresTablesTreeItem.ts @@ -5,47 +5,54 @@ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { ThemeIcon } from 'vscode'; +import { ThemeIcon } from "vscode"; import { getTables, IPostgresTable } from "../getTables"; import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = 'Tables'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); - } - return tables.map(table => new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } + public static contextValue: string = "postgresTables"; + public readonly contextValue: string = PostgresTablesTreeItem.contextValue; + public readonly childTypeLabel: string = "Table"; + public readonly label: string = "Tables"; + public suppressMaskLabel = true; + + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } + + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("window"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const tables: IPostgresTable[] = await getTables(this.clientConfig); + this.resourcesAndSchemas = {}; + for (const table of tables) { + this.addResourcesAndSchemasEntry( + table.name.trim(), + table.schemaName + ); + } + return tables.map( + (table) => + new PostgresTableTreeItem( + this, + table, + this.isDuplicateResource(table.name.trim()) + ) + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresTableTreeItem.contextValue; + } } diff --git a/Source/resolver/AppResolver.ts b/Source/resolver/AppResolver.ts index 0f75cdf29..7d20a4832 100644 --- a/Source/resolver/AppResolver.ts +++ b/Source/resolver/AppResolver.ts @@ -4,8 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; -import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, + ISubscriptionContext, + nonNullProp, + nonNullValue, +} from "@microsoft/vscode-azext-utils"; +import { + AppResource, + AppResourceResolver, +} from "@microsoft/vscode-azext-utils/hostapi"; import { tryGetExperience } from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; import { ext } from "../extensionVariables"; @@ -13,59 +24,111 @@ import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresAbstractServer } from "../postgres/abstract/models"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; +import { + createCosmosDBClient, + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../utils/azureClients"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; const resourceTypes = [ - 'microsoft.documentdb/databaseaccounts', - 'microsoft.dbforpostgresql/servers', - 'microsoft.dbforpostgresql/flexibleservers' + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers", ]; export class DatabaseResolver implements AppResourceResolver { - public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { - return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); - try { - const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); - const name = nonNullProp(resource, 'name'); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; + public async resolveResource( + subContext: ISubscriptionContext, + resource: AppResource + ): Promise { + return await callWithTelemetryAndErrorHandling( + "resolveResource", + async (context: IActionContext) => { + const subNode: AzExtParentTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + `/subscriptions/${subContext.subscriptionId}`, + context + ); + try { + const resourceGroupName = getResourceGroupFromId( + nonNullProp(resource, "id") + ); + const name = nonNullProp(resource, "name"); + let postgresServer: PostgresAbstractServer; + let dbChild: AzExtTreeItem; - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ ...context, ...subContext }); - const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); - const experience = tryGetExperience(databaseAccount); + switch (resource.type.toLowerCase()) { + case resourceTypes[0]: + const client = await createCosmosDBClient({ + ...context, + ...subContext, + }); + const databaseAccount = + await client.databaseAccounts.get( + resourceGroupName, + name + ); + dbChild = + await SubscriptionTreeItem.initCosmosDBChild( + client, + databaseAccount, + nonNullValue(subNode) + ); + const experience = + tryGetExperience(databaseAccount); - return experience?.api === 'MongoDB' ? - new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : - new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? - await createPostgreSQLClient({ ...context, ...subContext }) : - await createPostgreSQLFlexibleClient({ ...context, ...subContext }); + return experience?.api === "MongoDB" + ? new ResolvedMongoAccountResource( + dbChild as MongoAccountTreeItem, + resource + ) + : new ResolvedDocDBAccountResource( + dbChild as DocDBAccountTreeItem, + resource + ); + case resourceTypes[1]: + case resourceTypes[2]: + const postgresClient = + resource.type.toLowerCase() === resourceTypes[1] + ? await createPostgreSQLClient({ + ...context, + ...subContext, + }) + : await createPostgreSQLFlexibleClient({ + ...context, + ...subContext, + }); - postgresServer = await postgresClient.servers.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); + postgresServer = await postgresClient.servers.get( + resourceGroupName, + name + ); + dbChild = + await SubscriptionTreeItem.initPostgresChild( + postgresServer, + nonNullValue(subNode) + ); - return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - }); - } + return new ResolvedPostgresServerResource( + dbChild as PostgresServerTreeItem, + resource + ); + default: + return null; + } + } catch (e) { + console.error({ ...context, ...subContext }); + throw e; + } + } + ); + } - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } + public matchesResource(resource: AppResource): boolean { + return resourceTypes.includes(resource.type.toLowerCase()); + } } diff --git a/Source/resolver/DatabaseWorkspaceProvider.ts b/Source/resolver/DatabaseWorkspaceProvider.ts index 14e50d643..d1f462a36 100644 --- a/Source/resolver/DatabaseWorkspaceProvider.ts +++ b/Source/resolver/DatabaseWorkspaceProvider.ts @@ -3,31 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; import { Disposable } from "vscode"; import { ext } from "../extensionVariables"; import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; - export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise { - - return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - }); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } + public disposables: Disposable[] = []; + + constructor(parent: AzExtParentTreeItem) { + ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); + } + + public async provideResources(): Promise< + AzExtTreeItem[] | null | undefined + > { + return await callWithTelemetryAndErrorHandling( + "AzureAccountTreeItemWithProjects.provideResources", + async (_context: IActionContext) => { + return [ext.attachedAccountsNode]; + } + ); + } + private _projectDisposables: Disposable[] = []; + + public dispose(): void { + Disposable.from(...this._projectDisposables).dispose(); + } } - diff --git a/Source/resolver/ResolvedDatabaseAccountResource.ts b/Source/resolver/ResolvedDatabaseAccountResource.ts index 0222dded7..41eda32be 100644 --- a/Source/resolver/ResolvedDatabaseAccountResource.ts +++ b/Source/resolver/ResolvedDatabaseAccountResource.ts @@ -3,55 +3,78 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AzExtTreeItem, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue) - this.maskedValuestoAdd.push(...ti.valuesToMask); - } +export class ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public id: string; + public contextValuesToAdd: string[] = []; + public description: string | undefined; + + // private _databaseTreeItem: AzExtParentTreeItem; + iconPath: TreeItemIconPath | undefined; + label: string; + + readonly childTypeLabel: string; + + loadMoreChildrenImpl?( + clearCache: boolean, + context: IActionContext + ): Promise; + createChildImpl?(context: ICreateChildImplContext): Promise; + hasMoreChildrenImpl?(): boolean; + compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; + + pickTreeItemImpl?( + expectedContextValues: (string | RegExp)[], + context: IActionContext + ): AzExtTreeItem | undefined | Promise; + deleteTreeItemImpl?(context: IActionContext): Promise; + refreshImpl?(context: IActionContext): Promise; + isAncestorOfImpl?(contextValue: string): boolean; + + connectionString: string; + maskedValuestoAdd: string[] = []; + + public constructor( + ti: + | DocDBAccountTreeItemBase + | MongoAccountTreeItem + | PostgresServerTreeItem, + resource: AppResource + ) { + this.id = ti.id ?? resource.id; + // PostgresServerTreeItem require on a property on the server so wait to do this + this.description = + ti instanceof PostgresServerTreeItem ? undefined : ti.description; + this.iconPath = ti.iconPath; + this.label = ti.label; + this.childTypeLabel = ti.childTypeLabel; + + this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; + this.createChildImpl = ti.createChildImpl; + this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; + this.compareChildrenImpl = ti.compareChildrenImpl; + + this.pickTreeItemImpl = ti.pickTreeItemImpl; + this.deleteTreeItemImpl = ti.deleteTreeItemImpl; + this.refreshImpl = ti.refreshImpl; + this.isAncestorOfImpl = ti.isAncestorOfImpl; + + this.contextValuesToAdd.push(ti.contextValue); + this.maskedValuestoAdd.push(...ti.valuesToMask); + } } diff --git a/Source/resolver/ResolvedDocDBAccountResource.ts b/Source/resolver/ResolvedDocDBAccountResource.ts index cf1bfc4bc..02f17f6e3 100644 --- a/Source/resolver/ResolvedDocDBAccountResource.ts +++ b/Source/resolver/ResolvedDocDBAccountResource.ts @@ -1,32 +1,45 @@ - - /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + CosmosClient, + DatabaseDefinition, + FeedOptions, + QueryIterator, + Resource, +} from "@azure/cosmos"; import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } +export class ResolvedDocDBAccountResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public root: IDocDBTreeRoot; + + initChild: (resource: Resource) => AzExtTreeItem; + isServerless?: boolean; + getIterator?: ( + client: CosmosClient, + feedOptions: FeedOptions + ) => QueryIterator; + + public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { + super(ti, resource); + + this.connectionString = ti.connectionString; + this.root = ti.root; + + this.isServerless = ti.isServerless; + this.getIterator = ti.getIterator; + this.initChild = ti.initChild; + } } diff --git a/Source/resolver/ResolvedMongoAccountResource.ts b/Source/resolver/ResolvedMongoAccountResource.ts index 4f45486ef..80636b5e5 100644 --- a/Source/resolver/ResolvedMongoAccountResource.ts +++ b/Source/resolver/ResolvedMongoAccountResource.ts @@ -3,18 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - root: IMongoTreeRoot; +export class ResolvedMongoAccountResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + root: IMongoTreeRoot; - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); + public constructor(ti: MongoAccountTreeItem, resource: AppResource) { + super(ti, resource); - this.connectionString = ti.connectionString; - this.root = ti.root; - } + this.connectionString = ti.connectionString; + this.root = ti.root; + } } diff --git a/Source/resolver/ResolvedPostgresServerResource.ts b/Source/resolver/ResolvedPostgresServerResource.ts index a1e35acf3..76007eac0 100644 --- a/Source/resolver/ResolvedPostgresServerResource.ts +++ b/Source/resolver/ResolvedPostgresServerResource.ts @@ -4,45 +4,54 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { ClientConfig } from "pg"; import { PostgresServerType } from "../postgres/abstract/models"; import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise - deletePostgresCredentials: () => Promise - getFullConnectionString: () => Promise - validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise - isFirewallRuleSet: (context: IActionContext) => Promise - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } +export class ResolvedPostgresServerResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public readonly serverType?: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + setCredentials: (username: string, password: string) => void; + supportsStoredProcedures: (clientConfig: ClientConfig) => Promise; + deletePostgresCredentials: () => Promise; + getFullConnectionString: () => Promise; + validateDatabaseName: ( + name: string, + getChildrenTask: Promise + ) => Promise; + isFirewallRuleSet: (context: IActionContext) => Promise; + + public constructor(ti: PostgresServerTreeItem, resource: AppResource) { + super(ti, resource); + this.serverType = ti.serverType; + this.description = ti.description; + this.resourceGroup = ti.resourceGroup; + this.azureName = ti.azureName; + this.partialConnectionString = ti.partialConnectionString; + + this.azureId = ti.azureId; + this.serverVersion = ti.serverVersion; + + this.setCredentials = ti.setCredentials; + this.supportsStoredProcedures = ti.supportsStoredProcedures; + this.deletePostgresCredentials = ti.deletePostgresCredentials; + this.getFullConnectionString = ti.getFullConnectionString; + this.isFirewallRuleSet = ti.isFirewallRuleSet; + } } diff --git a/Source/table/tree/TableAccountTreeItem.ts b/Source/table/tree/TableAccountTreeItem.ts index 0d3b86e38..fb2616da9 100644 --- a/Source/table/tree/TableAccountTreeItem.ts +++ b/Source/table/tree/TableAccountTreeItem.ts @@ -4,36 +4,40 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBTableAccount"; + public contextValue: string = TableAccountTreeItem.contextValue; - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public initChild(): AzExtTreeItem { - throw new Error('Table Accounts are not supported yet.'); - } + public initChild(): AzExtTreeItem { + throw new Error("Table Accounts are not supported yet."); + } - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'tableNotSupported', - label: 'Table Accounts are not supported yet.' - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: "tableNotSupported", + label: "Table Accounts are not supported yet.", + }); + tableNotFoundTreeItem.suppressMaskLabel = true; + return [tableNotFoundTreeItem]; + } - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } - public isAncestorOfImpl(): boolean { - return false; - } + public isAncestorOfImpl(): boolean { + return false; + } } diff --git a/Source/tree/AttachedAccountsTreeItem.ts b/Source/tree/AttachedAccountsTreeItem.ts index d854e506f..47aa8bdc3 100644 --- a/Source/tree/AttachedAccountsTreeItem.ts +++ b/Source/tree/AttachedAccountsTreeItem.ts @@ -3,418 +3,605 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { removeTreeItemFromCache } from '../commands/api/apiCache'; -import { emulatorPassword, isWindows } from '../constants'; -import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; -import { connectToMongoClient } from '../mongo/connectToMongoClient'; -import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; -import { getSecretStorageKey } from '../utils/getSecretStorageKey'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + AzExtTreeItem, + GenericTreeItem, + IActionContext, + ISubscriptionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { MongoClient } from "mongodb"; +import * as vscode from "vscode"; +import { + API, + getExperienceFromApi, + getExperienceQuickPick, + getExperienceQuickPicks, +} from "../AzureDBExperiences"; +import { removeTreeItemFromCache } from "../commands/api/apiCache"; +import { emulatorPassword, isWindows } from "../constants"; +import { parseDocDBConnectionString } from "../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; +import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../extensionVariables"; +import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; +import { connectToMongoClient } from "../mongo/connectToMongoClient"; +import { parseMongoConnectionString } from "../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { parsePostgresConnectionString } from "../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; +import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; +import { getSecretStorageKey } from "../utils/getSecretStorageKey"; +import { localize } from "../utils/localize"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; + id: string; + // defaultExperience is not the same as API but we can't change the name due to backwards compatibility + defaultExperience: API; + isEmulator: boolean | undefined; } -export const AttachedAccountSuffix: string = 'Attached'; -export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; +export const AttachedAccountSuffix: string = "Attached"; +export const MONGO_CONNECTION_EXPECTED: string = + 'Connection string must start with "mongodb://" or "mongodb+srv://"'; -const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; +const localMongoConnectionString: string = "mongodb://127.0.0.1:27017"; export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); - public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; - public readonly label: string = 'Attached Database Accounts'; - public childTypeLabel: string = 'Account'; - public suppressMaskLabel = true; - - private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = 'cosmosDBAttachedAccounts'; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('plug'); - } - - public static validateMongoConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); - } - - private static validateDocDBConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachDatabaseAccount', - label: 'Attach Database Account...', - commandId: 'cosmosDB.attachDatabaseAccount', - includeInTreeItemPicker: true - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachEmulator', - label: 'Attach Emulator...', - commandId: 'cosmosDB.attachEmulator', - includeInTreeItemPicker: true - }); - return isWindows ? [attachDatabaseAccount, attachEmulator] : - [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = 'mongodb://host:port'; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; - } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { - placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); - validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = 'AccountEndpoint=...;AccountKey=...'; - validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = (await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: 'Enter the connection string for your database account', - stepName: 'attachNewAccountConnectionString', - validateInput: validateInput, - value: defaultValue - })).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { - const treeItem = await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core) - ], - { - placeHolder: "Select a Database Account API...", - stepName: 'attachEmulator' - }); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); - if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.find(s => s.id === treeItem.id)) { - void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get(this._serviceName); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all(accounts.map(async account => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof (account) === 'string') { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${getExperienceFromApi(api).shortName})`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); - persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); - })); - } - - return persistedAccounts; - } - - private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error(`Unexpected account node "${node.constructor.name}".`); - } - return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; - }); - await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); - } + public static contextValue: string = + "cosmosDBAttachedAccounts" + + (isWindows ? "WithEmulator" : "WithoutEmulator"); + public readonly contextValue: string = + AttachedAccountsTreeItem.contextValue; + public readonly label: string = "Attached Database Accounts"; + public childTypeLabel: string = "Account"; + public suppressMaskLabel = true; + + private readonly _serviceName: string = + "ms-azuretools.vscode-cosmosdb.connectionStrings"; + private _attachedAccounts: AzExtTreeItem[] | undefined; + + private _root: ISubscriptionContext; + private _loadPersistedAccountsTask: Promise; + + constructor(parent: AzExtParentTreeItem) { + super(parent); + this._root = new AttachedAccountRoot(); + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + this.id = "cosmosDBAttachedAccounts"; + } + + public get root(): ISubscriptionContext { + return this._root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("plug"); + } + + public static validateMongoConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + if (value && value.match(/^mongodb(\+srv)?:\/\//)) { + return undefined; + } + + return MONGO_CONNECTION_EXPECTED; + } + + public static validatePostgresConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + if (value && value.match(/^postgres:\/\//)) { + return undefined; + } + + return localize( + "invalidPostgresConnectionString", + 'Connection string must start with "postgres://"' + ); + } + + private static validateDocDBConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + try { + parseDocDBConnectionString(value); + return undefined; + } catch (error) { + return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache) { + this._attachedAccounts = undefined; + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + } + + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + if (attachedAccounts.length > 0) { + return attachedAccounts; + } else { + const attachDatabaseAccount = new GenericTreeItem(this, { + contextValue: "cosmosDBAttachDatabaseAccount", + label: "Attach Database Account...", + commandId: "cosmosDB.attachDatabaseAccount", + includeInTreeItemPicker: true, + }); + const attachEmulator = new GenericTreeItem(this, { + contextValue: "cosmosDBAttachEmulator", + label: "Attach Emulator...", + commandId: "cosmosDB.attachEmulator", + includeInTreeItemPicker: true, + }); + return isWindows + ? [attachDatabaseAccount, attachEmulator] + : [attachDatabaseAccount]; + } + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + // We have to make sure the Attached Accounts node is not shown for commands like + // 'Open in Portal', which only work for the non-attached version + case GraphAccountTreeItem.contextValue: + case MongoAccountTreeItem.contextValue: + case DocDBAccountTreeItem.contextValue: + case TableAccountTreeItem.contextValue: + case PostgresServerTreeItem.contextValue: + case SubscriptionTreeItem.contextValue: + return false; + default: + return true; + } + } + + public async attachNewAccount(context: IActionContext): Promise { + const defaultExperiencePick = await context.ui.showQuickPick( + getExperienceQuickPicks(true), + { + placeHolder: "Select a Database type...", + stepName: "attachNewAccount", + } + ); + const defaultExperience = defaultExperiencePick.data; + let placeholder: string; + let defaultValue: string | undefined; + let validateInput: (value: string) => string | undefined | null; + if (defaultExperience.api === API.MongoDB) { + placeholder = "mongodb://host:port"; + if (await this.canConnectToLocalMongoDB()) { + defaultValue = placeholder = localMongoConnectionString; + } + validateInput = + AttachedAccountsTreeItem.validateMongoConnectionString; + } else if ( + defaultExperience.api === API.PostgresSingle || + defaultExperience.api === API.PostgresFlexible + ) { + placeholder = localize( + "attachedPostgresPlaceholder", + '"postgres://username:password@host" or "postgres://username:password@host/database"' + ); + validateInput = + AttachedAccountsTreeItem.validatePostgresConnectionString; + } else { + placeholder = "AccountEndpoint=...;AccountKey=..."; + validateInput = + AttachedAccountsTreeItem.validateDocDBConnectionString; + } + + const connectionString = ( + await context.ui.showInputBox({ + placeHolder: placeholder, + prompt: "Enter the connection string for your database account", + stepName: "attachNewAccountConnectionString", + validateInput: validateInput, + value: defaultValue, + }) + ).trim(); + + const treeItem: AzExtTreeItem = await this.createTreeItem( + connectionString, + defaultExperience.api + ); + await this.attachAccount(context, treeItem, connectionString); + } + + public async attachConnectionString( + context: IActionContext, + connectionString: string, + api: API.MongoDB | API.Core | API.PostgresSingle + ): Promise< + MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem + > { + const treeItem = < + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + >await this.createTreeItem(connectionString, api); + await this.attachAccount(context, treeItem, connectionString); + await this.refresh(context); + return treeItem; + } + + public async attachEmulator(context: IActionContext): Promise { + let connectionString: string; + const defaultExperiencePick = await context.ui.showQuickPick( + [ + getExperienceQuickPick(API.MongoDB), + getExperienceQuickPick(API.Core), + ], + { + placeHolder: "Select a Database Account API...", + stepName: "attachEmulator", + } + ); + const defaultExperience = defaultExperiencePick.data; + let port: number | undefined; + if (defaultExperience.api === API.MongoDB) { + port = vscode.workspace + .getConfiguration() + .get("cosmosDB.emulator.mongoPort"); + } else { + port = vscode.workspace + .getConfiguration() + .get("cosmosDB.emulator.port"); + } + if (port) { + if (defaultExperience.api === API.MongoDB) { + // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions + connectionString = `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:${port}/?ssl=true`; + } else { + connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; + } + const label = `${defaultExperience.shortName} Emulator`; + const treeItem: AzExtTreeItem = await this.createTreeItem( + connectionString, + defaultExperience.api, + label + ); + if ( + treeItem instanceof DocDBAccountTreeItem || + treeItem instanceof GraphAccountTreeItem || + treeItem instanceof TableAccountTreeItem || + treeItem instanceof MongoAccountTreeItem + ) { + // CONSIDER: Why isn't this passed in to createTreeItem above? + treeItem.root.isEmulator = true; + } + await this.attachAccount(context, treeItem, connectionString); + } + } + + public async detach(node: AzExtTreeItem): Promise { + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + const index = attachedAccounts.findIndex( + (account) => account.fullId === node.fullId + ); + if (index !== -1) { + attachedAccounts.splice(index, 1); + await ext.secretStorage.delete( + getSecretStorageKey(this._serviceName, nonNullProp(node, "id")) + ); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility + await this.persistIds(attachedAccounts); + + if (node instanceof MongoAccountTreeItem) { + const parsedCS = await parseMongoConnectionString( + node.connectionString + ); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof DocDBAccountTreeItemBase) { + const parsedCS = parseDocDBConnectionString( + node.connectionString + ); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof PostgresServerTreeItem) { + const parsedCS = node.partialConnectionString; + removeTreeItemFromCache(parsedCS); + } + } + } + + private async getAttachedAccounts(): Promise { + if (!this._attachedAccounts) { + try { + this._attachedAccounts = await this._loadPersistedAccountsTask; + } catch { + this._attachedAccounts = []; + throw new Error( + "Failed to load persisted Database Accounts. Reattach the accounts manually." + ); + } + } + + return this._attachedAccounts; + } + + private async canConnectToLocalMongoDB(): Promise { + async function timeout(): Promise { + await delay(1000); + return false; + } + async function connect(): Promise { + try { + const db: MongoClient = await connectToMongoClient( + localMongoConnectionString, + appendExtensionUserAgent() + ); + void db.close(); + return true; + } catch { + return false; + } + } + return await Promise.race([timeout(), connect()]); + } + + private async attachAccount( + context: IActionContext, + treeItem: AzExtTreeItem, + connectionString: string + ): Promise { + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + if (attachedAccounts.find((s) => s.id === treeItem.id)) { + void context.ui.showWarningMessage( + `Database Account '${treeItem.id}' is already attached.`, + { stepName: "attachAccount" } + ); + } else { + attachedAccounts.push(treeItem); + await ext.secretStorage.store( + getSecretStorageKey( + this._serviceName, + nonNullProp(treeItem, "id") + ), + connectionString + ); + await this.persistIds(attachedAccounts); + } + } + + private async loadPersistedAccounts(): Promise { + const persistedAccounts: AzExtTreeItem[] = []; + const value: string | undefined = ext.context.globalState.get( + this._serviceName + ); + if (value) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const accounts: (string | IPersistedAccount)[] = JSON.parse(value); + await Promise.all( + accounts.map(async (account) => { + let id: string; + let label: string; + let api: API; + let isEmulator: boolean | undefined; + if (typeof account === "string") { + // Default to Mongo if the value is a string for the sake of backwards compatibility + // (Mongo was originally the only account type that could be attached) + id = account; + api = API.MongoDB; + label = `${account} (${ + getExperienceFromApi(api).shortName + })`; + isEmulator = false; + } else { + id = (account).id; + api = (account).defaultExperience; + isEmulator = (account).isEmulator; + label = isEmulator + ? `${getExperienceFromApi(api).shortName} Emulator` + : `${id} (${getExperienceFromApi(api).shortName})`; + } + // TODO: keytar: migration plan? + const connectionString: string = nonNullValue( + await ext.secretStorage.get( + getSecretStorageKey(this._serviceName, id) + ), + "connectionString" + ); + persistedAccounts.push( + await this.createTreeItem( + connectionString, + api, + label, + id, + isEmulator + ) + ); + }) + ); + } + + return persistedAccounts; + } + + private async createTreeItem( + connectionString: string, + api: API, + label?: string, + id?: string, + isEmulator?: boolean + ): Promise { + let treeItem: AzExtTreeItem; + if (api === API.MongoDB) { + if (id === undefined) { + const parsedCS = + await parseMongoConnectionString(connectionString); + id = parsedCS.fullId; + } + + label = label || `${id} (${getExperienceFromApi(api).shortName})`; + treeItem = new MongoAccountTreeItem( + this, + id, + label, + connectionString, + isEmulator + ); + } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { + const parsedPostgresConnString = + parsePostgresConnectionString(connectionString); + treeItem = new PostgresServerTreeItem( + this, + parsedPostgresConnString + ); + } else { + const parsedCS = parseDocDBConnectionString(connectionString); + + label = + label || + `${parsedCS.accountId} (${ + getExperienceFromApi(api).shortName + })`; + switch (api) { + case API.Table: + treeItem = new TableAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + parsedCS.masterKey, + isEmulator + ); + break; + case API.Graph: + treeItem = new GraphAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + undefined, + parsedCS.masterKey, + isEmulator + ); + break; + case API.Core: + treeItem = new DocDBAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + parsedCS.masterKey, + isEmulator + ); + break; + default: + throw new Error(`Unexpected defaultExperience "${api}".`); + } + } + + treeItem.contextValue += AttachedAccountSuffix; + return treeItem; + } + + private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { + const value: IPersistedAccount[] = attachedAccounts.map( + (node: AzExtTreeItem) => { + let api: API; + let isEmulator: boolean | undefined; + if ( + node instanceof MongoAccountTreeItem || + node instanceof DocDBAccountTreeItem || + node instanceof GraphAccountTreeItem || + node instanceof TableAccountTreeItem + ) { + isEmulator = node.root.isEmulator; + } + if (node instanceof MongoAccountTreeItem) { + api = API.MongoDB; + } else if (node instanceof GraphAccountTreeItem) { + api = API.Graph; + } else if (node instanceof TableAccountTreeItem) { + api = API.Table; + } else if (node instanceof DocDBAccountTreeItem) { + api = API.Core; + } else if (node instanceof PostgresServerTreeItem) { + api = API.PostgresSingle; + } else { + throw new Error( + `Unexpected account node "${node.constructor.name}".` + ); + } + return { + id: nonNullProp(node, "id"), + defaultExperience: api, + isEmulator: isEmulator, + }; + } + ); + await ext.context.globalState.update( + this._serviceName, + JSON.stringify(value) + ); + } } class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); + private _error: Error = new Error( + "Cannot retrieve Azure subscription information for an attached account." + ); - public get credentials(): never { - throw this._error; - } + public get credentials(): never { + throw this._error; + } - public get subscriptionDisplayName(): never { - throw this._error; - } + public get subscriptionDisplayName(): never { + throw this._error; + } - public get subscriptionId(): never { - throw this._error; - } + public get subscriptionId(): never { + throw this._error; + } - public get subscriptionPath(): never { - throw this._error; - } + public get subscriptionPath(): never { + throw this._error; + } - public get tenantId(): never { - throw this._error; - } + public get tenantId(): never { + throw this._error; + } - public get userId(): never { - throw this._error; - } + public get userId(): never { + throw this._error; + } - public get environment(): never { - throw this._error; - } + public get environment(): never { + throw this._error; + } - public get isCustomCloud(): never { - throw this._error; - } + public get isCustomCloud(): never { + throw this._error; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/tree/AzureAccountTreeItemWithAttached.ts b/Source/tree/AzureAccountTreeItemWithAttached.ts index 172cd598f..ce1cdb8fd 100644 --- a/Source/tree/AzureAccountTreeItemWithAttached.ts +++ b/Source/tree/AzureAccountTreeItemWithAttached.ts @@ -3,34 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; -import { ext } from '../extensionVariables'; -import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; +import { AzureAccountTreeItemBase } from "@microsoft/vscode-azext-azureutils"; +import { + AzExtTreeItem, + IActionContext, + ISubscriptionContext, +} from "@microsoft/vscode-azext-utils"; +import { ext } from "../extensionVariables"; +import { AttachedAccountsTreeItem } from "./AttachedAccountsTreeItem"; +import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } + public constructor(testAccount?: {}) { + super(undefined, testAccount); + ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); + } - public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } + public createSubscriptionTreeItem( + root: ISubscriptionContext + ): SubscriptionTreeItem { + return new SubscriptionTreeItem(this, root); + } - public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); - return children.concat(ext.attachedAccountsNode); - } + public async loadMoreChildrenImpl( + clearCache: boolean, + context: IActionContext + ): Promise { + const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl( + clearCache, + context + ); + return children.concat(ext.attachedAccountsNode); + } - public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } + public compareChildrenImpl( + item1: AzExtTreeItem, + item2: AzExtTreeItem + ): number { + if (item1 instanceof AttachedAccountsTreeItem) { + return 1; + } else if (item2 instanceof AttachedAccountsTreeItem) { + return -1; + } else { + return super.compareChildrenImpl(item1, item2); + } + } } diff --git a/Source/tree/AzureDBAPIStep.ts b/Source/tree/AzureDBAPIStep.ts index 8a11fdc95..a59ebfd48 100644 --- a/Source/tree/AzureDBAPIStep.ts +++ b/Source/tree/AzureDBAPIStep.ts @@ -3,74 +3,103 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; -import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; -import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; -import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; -import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; -import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; -import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; -import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; -import { localize } from '../utils/localize'; -import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; -import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; -import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; -import { IAzureDBWizardContext } from './IAzureDBWizardContext'; +import { VerifyProvidersStep } from "@microsoft/vscode-azext-azureutils"; +import { + AzureWizardExecuteStep, + AzureWizardPromptStep, + IAzureQuickPickItem, + IWizardOptions, +} from "@microsoft/vscode-azext-utils"; +import { + API, + Experience, + getExperienceQuickPicks, +} from "../AzureDBExperiences"; +import { PostgresServerType } from "../postgres/abstract/models"; +import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; +import { PostgresServerConfirmPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep"; +import { PostgresServerCreateStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep"; +import { PostgresServerCredPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep"; +import { PostgresServerCredUserStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep"; +import { PostgresServerNameStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerNameStep"; +import { PostgresServerSetCredentialsStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep"; +import { PostgresServerSkuStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep"; +import { localize } from "../utils/localize"; +import { CosmosDBAccountCapacityStep } from "./CosmosDBAccountWizard/CosmosDBAccountCapacityStep"; +import { CosmosDBAccountCreateStep } from "./CosmosDBAccountWizard/CosmosDBAccountCreateStep"; +import { CosmosDBAccountNameStep } from "./CosmosDBAccountWizard/CosmosDBAccountNameStep"; +import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; +import { IAzureDBWizardContext } from "./IAzureDBWizardContext"; -export class AzureDBAPIStep extends AzureWizardPromptStep { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); +export class AzureDBAPIStep extends AzureWizardPromptStep< + IPostgresServerWizardContext | ICosmosDBWizardContext +> { + public async prompt(context: IAzureDBWizardContext): Promise { + const picks: IAzureQuickPickItem[] = + getExperienceQuickPicks(); - const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { - placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') - }); + const result: IAzureQuickPickItem = + await context.ui.showQuickPick(picks, { + placeHolder: localize( + "selectDBServerMsg", + "Select an Azure Database Server." + ), + }); - context.defaultExperience = result.data; - } + context.defaultExperience = result.data; + } - public async getSubWizard(context: IAzureDBWizardContext): Promise> { - let promptSteps: AzureWizardPromptStep[]; - let executeSteps: AzureWizardExecuteStep[]; - if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(['Microsoft.DocumentDB']) - ]; - } - return { promptSteps, executeSteps }; - } + public async getSubWizard( + context: IAzureDBWizardContext + ): Promise< + IWizardOptions + > { + let promptSteps: AzureWizardPromptStep< + IPostgresServerWizardContext | ICosmosDBWizardContext + >[]; + let executeSteps: AzureWizardExecuteStep< + IPostgresServerWizardContext | ICosmosDBWizardContext + >[]; + if ( + context.defaultExperience?.api === API.PostgresSingle || + context.defaultExperience?.api === API.PostgresFlexible + ) { + switch (context.defaultExperience?.api) { + case API.PostgresFlexible: + (context as IPostgresServerWizardContext).serverType = + PostgresServerType.Flexible; + break; + case API.PostgresSingle: + (context as IPostgresServerWizardContext).serverType = + PostgresServerType.Single; + break; + } + promptSteps = [ + new PostgresServerNameStep(), + new PostgresServerSkuStep(), + new PostgresServerCredUserStep(), + new PostgresServerCredPWStep(), + new PostgresServerConfirmPWStep(), + ]; + executeSteps = [ + new PostgresServerCreateStep(), + new PostgresServerSetCredentialsStep(), + new VerifyProvidersStep(["Microsoft.DBforPostgreSQL"]), + ]; + } else { + promptSteps = [ + new CosmosDBAccountNameStep(), + new CosmosDBAccountCapacityStep(), + ]; + executeSteps = [ + new CosmosDBAccountCreateStep(), + new VerifyProvidersStep(["Microsoft.DocumentDB"]), + ]; + } + return { promptSteps, executeSteps }; + } - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } + public shouldPrompt(context: IAzureDBWizardContext): boolean { + return !context.defaultExperience; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts index b46453e3a..192e5fa54 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts @@ -3,38 +3,53 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, +} from "@microsoft/vscode-azext-utils"; +import { localize } from "../../utils/localize"; +import { openUrl } from "../../utils/openUrl"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { + public async prompt(context: ICosmosDBWizardContext): Promise { + const placeHolder: string = localize( + "selectDBServerMsg", + "Select a capacity model." + ); + const picks: IAzureQuickPickItem[] = [ + { + label: localize("provisionedOption", "Provisioned Throughput"), + data: false, + }, + { label: localize("serverlessOption", "Serverless"), data: true }, + ]; + const learnMore: IAzureQuickPickItem = { + label: localize("learnMore", "$(link-external) Learn more..."), + data: undefined, + }; + picks.push(learnMore); + let pick: IAzureQuickPickItem; - public async prompt(context: ICosmosDBWizardContext): Promise { + do { + pick = await context.ui.showQuickPick(picks, { + placeHolder, + suppressPersistence: true, + }); + if (pick === learnMore) { + await openUrl("https://aka.ms/cosmos-models"); + } + } while (pick === learnMore); - const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') - const picks: IAzureQuickPickItem[] = [ - { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, - { label: localize('serverlessOption', 'Serverless'), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; + if (pick.data) { + context.isServerless = pick.data; + context.telemetry.properties.isServerless = pick.data + ? "true" + : "false"; + } + } - do { - pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); - if (pick === learnMore) { - await openUrl('https://aka.ms/cosmos-models'); - } - } while (pick === learnMore); - - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; - } - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return context.isServerless === undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts index 4bd469b84..f0eadf3a3 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts @@ -3,61 +3,81 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; -import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { Progress } from 'vscode'; -import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { DatabaseAccountCreateUpdateParameters } from "@azure/arm-cosmosdb/src/models"; +import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; +import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; +import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; +import { Progress } from "vscode"; +import { SERVERLESS_CAPABILITY_NAME } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const locationName: string = (await LocationListStep.getLocation(context)).name; - const defaultExperience = nonNullProp(context, 'defaultExperience'); - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const accountName = nonNullProp(context, 'newServerName'); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: 'Standard', - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, - }; - - if (defaultExperience?.api === 'MongoDB') { - options.apiProperties = { serverVersion: '3.6' }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } + public priority: number = 130; + + public async execute( + context: ICosmosDBWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + const locationName: string = ( + await LocationListStep.getLocation(context) + ).name; + const defaultExperience = nonNullProp(context, "defaultExperience"); + const rgName: string = nonNullProp( + nonNullProp(context, "resourceGroup"), + "name" + ); + const accountName = nonNullProp(context, "newServerName"); + + const client = await createCosmosDBClient(context); + const creatingMessage: string = localize( + "creatingCosmosDBAccount", + 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', + accountName, + defaultExperience.shortName + ); + ext.outputChannel.appendLog(creatingMessage); + progress.report({ message: creatingMessage }); + + const options: DatabaseAccountCreateUpdateParameters = { + location: locationName, + locations: [{ locationName: locationName }], + kind: defaultExperience.kind, + capabilities: [], + databaseAccountOfferType: "Standard", + // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior + tags: { defaultExperience: nonNullProp(defaultExperience, "tag") }, + }; + + if (defaultExperience?.api === "MongoDB") { + options.apiProperties = { serverVersion: "3.6" }; + } + + if (defaultExperience.capability) { + options.capabilities?.push({ name: defaultExperience.capability }); + } + + if (context.isServerless) { + options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); + } + + context.databaseAccount = + await client.databaseAccounts.beginCreateOrUpdateAndWait( + rgName, + accountName, + options + ); + context.activityResult = context.databaseAccount as AppResource; + + ext.outputChannel.appendLog( + `Successfully created Cosmos DB account "${accountName}".` + ); + } + + public shouldExecute(context: ICosmosDBWizardContext): boolean { + return !context.databaseAccount; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts index 87ef6be61..222736605 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts @@ -3,47 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { + ResourceGroupListStep, + resourceGroupNamingRules, +} from "@microsoft/vscode-azext-azureutils"; +import { AzureNameStep } from "@microsoft/vscode-azext-utils"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountNameStep extends AzureNameStep { + public async prompt(context: ICosmosDBWizardContext): Promise { + const client = await createCosmosDBClient(context); + context.newServerName = ( + await context.ui.showInputBox({ + placeHolder: "Account name", + prompt: "Provide a Cosmos DB account name", + validateInput: (name: string) => + validateCosmosDBAccountName(name, client), + }) + ).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName( + context, + context.newServerName, + resourceGroupNamingRules + ); + } - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => validateCosmosDBAccountName(name, client) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return !context.newServerName; + } - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + protected async isRelatedNameAvailable( + context: ICosmosDBWizardContext, + name: string + ): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { - name = name ? name.trim() : ''; +async function validateCosmosDBAccountName( + name: string, + client: CosmosDBManagementClient +): Promise { + name = name ? name.trim() : ""; - const min = 3; - const max = 31; + const min = 3; + const max = 31; - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } + if (name.length < min || name.length > max) { + return `The name must be between ${min} and ${max} characters.`; + } else if (name.match(/[^a-z0-9-]/)) { + return "The name can only contain lowercase letters, numbers, and the '-' character."; + } else if ((await client.databaseAccounts.checkNameExists(name)).body) { + return `Account name "${name}" is not available.`; + } else { + return undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts index 61666a859..cc12a75ed 100644 --- a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; - -export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb"; +import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; +import { IAzureDBWizardContext } from "../IAzureDBWizardContext"; +export interface ICosmosDBWizardContext + extends IAzureDBWizardContext, + ExecuteActivityContext { + /** + * The newly created Cosmos DB account + * This will be defined after `CosmosDBAccountStep.execute` occurs. + */ + databaseAccount?: DatabaseAccountGetResults; + isServerless?: boolean; } diff --git a/Source/tree/IAzureDBWizardContext.ts b/Source/tree/IAzureDBWizardContext.ts index fd84ff0d5..5f6946275 100644 --- a/Source/tree/IAzureDBWizardContext.ts +++ b/Source/tree/IAzureDBWizardContext.ts @@ -3,12 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { Experience } from '../AzureDBExperiences'; +import { IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; +import { Experience } from "../AzureDBExperiences"; export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - - newServerName?: string; - defaultExperience?: Experience; - + newServerName?: string; + defaultExperience?: Experience; } diff --git a/Source/tree/SubscriptionTreeItem.ts b/Source/tree/SubscriptionTreeItem.ts index 910d8d970..93cb2173a 100644 --- a/Source/tree/SubscriptionTreeItem.ts +++ b/Source/tree/SubscriptionTreeItem.ts @@ -3,156 +3,322 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; -import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { + DatabaseAccountGetResults, + DatabaseAccountListKeysResult, +} from "@azure/arm-cosmosdb/src/models"; +import { + getResourceGroupFromId, + ILocationWizardContext, + LocationListStep, + ResourceGroupListStep, + SubscriptionTreeItemBase, + uiUtils, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + AzureWizard, + AzureWizardPromptStep, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { + API, + Experience, + getExperienceLabel, + tryGetExperience, +} from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from '../extensionVariables'; -import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; +import { ext } from "../extensionVariables"; +import { tryGetGremlinEndpointFromAzure } from "../graph/gremlinEndpoints"; import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { + PostgresAbstractServer, + PostgresServerType, +} from "../postgres/abstract/models"; +import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; +import { + createPostgresConnectionString, + ParsedPostgresConnectionString, + parsePostgresConnectionString, +} from "../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from '../utils/activityUtils'; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { localize } from '../utils/localize'; -import { nonNullProp } from '../utils/nonNull'; -import { AzureDBAPIStep } from './AzureDBAPIStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; +import { createActivityContext } from "../utils/activityUtils"; +import { + createCosmosDBClient, + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../utils/azureClients"; +import { localize } from "../utils/localize"; +import { nonNullProp } from "../utils/nonNull"; +import { AzureDBAPIStep } from "./AzureDBAPIStep"; +import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = 'Account'; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - - //Postgres - const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); - const postgresServers: PostgresAbstractServer[] = [ - ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), - ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), - ]; - - const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - postgresServers, - 'invalidPostgreSQLAccount', - async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); - const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - accounts, - 'invalidCosmosDBAccount', - async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep() - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize('createDBServerMsg', 'Create new Azure Database Server') - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp(wizardContext, 'newServerName'); - wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { - const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, 'server'); - const host = nonNullProp(server, 'fullyQualifiedDomainName'); - const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); - const password: string = nonNullProp(wizardContext, 'adminPassword'); - const connectionString: string = createPostgresConnectionString(host, undefined, username, password); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return typeof contextValue !== 'string' || !/attached/i.test(contextValue); - } - - public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, 'id'); - const name: string = nonNullProp(databaseAccount, 'name'); - const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); - const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = 'retrywrites'; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, 'false'); - } - - // Use the default connection string - return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); - } else { - const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - case "Graph": { - const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); - return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - - } - } - } - public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { - const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } + public childTypeLabel: string = "Account"; + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + //Postgres + const postgresSingleClient = await createPostgreSQLClient([ + context, + this.subscription, + ]); + const postgresFlexibleClient = await createPostgreSQLFlexibleClient([ + context, + this.subscription, + ]); + const postgresServers: PostgresAbstractServer[] = [ + ...( + await uiUtils.listAllIterator( + postgresSingleClient.servers.list() + ) + ).map((s) => + Object.assign(s, { serverType: PostgresServerType.Single }) + ), + ...( + await uiUtils.listAllIterator( + postgresFlexibleClient.servers.list() + ) + ).map((s) => + Object.assign(s, { serverType: PostgresServerType.Flexible }) + ), + ]; + + const treeItemPostgres: AzExtTreeItem[] = + await this.createTreeItemsWithErrorHandling( + postgresServers, + "invalidPostgreSQLAccount", + async (server: PostgresAbstractServer) => + await SubscriptionTreeItem.initPostgresChild(server, this), + (server: PostgresAbstractServer) => server.name + ); + + //CosmosDB + const client = await createCosmosDBClient([context, this]); + const accounts = await uiUtils.listAllIterator( + client.databaseAccounts.list() + ); + const treeItem: AzExtTreeItem[] = + await this.createTreeItemsWithErrorHandling( + accounts, + "invalidCosmosDBAccount", + async (db: DatabaseAccountGetResults) => + await SubscriptionTreeItem.initCosmosDBChild( + client, + db, + this + ), + (db: DatabaseAccountGetResults) => db.name + ); + + treeItem.push(...treeItemPostgres); + return treeItem; + } + + public static async createChild( + context: IActionContext & { defaultExperience?: Experience }, + node: SubscriptionTreeItem + ): Promise { + const client = await createCosmosDBClient([context, node.subscription]); + const wizardContext: IPostgresServerWizardContext & + ICosmosDBWizardContext = Object.assign(context, node.subscription, { + ...(await createActivityContext()), + }); + + const promptSteps: AzureWizardPromptStep[] = [ + new AzureDBAPIStep(), + new ResourceGroupListStep(), + ]; + LocationListStep.addStep(wizardContext, promptSteps); + + const wizard = new AzureWizard(wizardContext, { + promptSteps, + executeSteps: [], + title: localize( + "createDBServerMsg", + "Create new Azure Database Server" + ), + }); + + await wizard.prompt(); + + wizardContext.telemetry.properties.defaultExperience = + wizardContext.defaultExperience?.api; + + const newServerName: string = nonNullProp( + wizardContext, + "newServerName" + ); + wizardContext.activityTitle = localize( + "createDBServerMsgActivityTitle", + 'Create new Azure Database Server "{0}"', + newServerName + ); + + await wizard.execute(); + await ext.rgApi.appResourceTree.refresh(context); + if ( + wizardContext.defaultExperience?.api === API.PostgresSingle || + wizardContext.defaultExperience?.api === API.PostgresFlexible + ) { + const createMessage: string = localize( + "createdServerOutput", + 'Successfully created PostgreSQL server "{0}".', + wizardContext.newServerName + ); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); + const server = nonNullProp(wizardContext, "server"); + const host = nonNullProp(server, "fullyQualifiedDomainName"); + const username: string = + wizardContext.serverType === PostgresServerType.Flexible + ? nonNullProp(wizardContext, "shortUserName") + : nonNullProp(wizardContext, "longUserName"); + const password: string = nonNullProp( + wizardContext, + "adminPassword" + ); + const connectionString: string = createPostgresConnectionString( + host, + undefined, + username, + password + ); + const parsedCS: ParsedPostgresConnectionString = + parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(node, parsedCS, server); + } else { + return await SubscriptionTreeItem.initCosmosDBChild( + client, + nonNullProp(wizardContext, "databaseAccount"), + node + ); + } + } + + public isAncestorOfImpl(contextValue: string | RegExp): boolean { + return ( + typeof contextValue !== "string" || !/attached/i.test(contextValue) + ); + } + + public static async initCosmosDBChild( + client: CosmosDBManagementClient, + databaseAccount: DatabaseAccountGetResults, + parent: AzExtParentTreeItem + ): Promise { + const experience = tryGetExperience(databaseAccount); + const id: string = nonNullProp(databaseAccount, "id"); + const name: string = nonNullProp(databaseAccount, "name"); + const documentEndpoint: string = nonNullProp( + databaseAccount, + "documentEndpoint" + ); + + const resourceGroup: string = getResourceGroupFromId(id); + const accountKindLabel = getExperienceLabel(databaseAccount); + const label: string = + name + (accountKindLabel ? ` (${accountKindLabel})` : ``); + const isEmulator: boolean = false; + + if (experience && experience.api === "MongoDB") { + const result = await client.databaseAccounts.listConnectionStrings( + resourceGroup, + name + ); + const connectionString: URL = new URL( + nonNullProp( + nonNullProp(result, "connectionStrings")[0], + "connectionString" + ) + ); + // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites + // but the newer node.js drivers started breaking this + const searchParam: string = "retrywrites"; + if (!connectionString.searchParams.has(searchParam)) { + connectionString.searchParams.set(searchParam, "false"); + } + + // Use the default connection string + return new MongoAccountTreeItem( + parent, + id, + label, + connectionString.toString(), + isEmulator, + databaseAccount + ); + } else { + const keyResult: DatabaseAccountListKeysResult = + await client.databaseAccounts.listKeys(resourceGroup, name); + const primaryMasterKey: string = nonNullProp( + keyResult, + "primaryMasterKey" + ); + switch (experience && experience.api) { + case "Table": + return new TableAccountTreeItem( + parent, + id, + label, + documentEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + case "Graph": { + const gremlinEndpoint = + await tryGetGremlinEndpointFromAzure( + client, + resourceGroup, + name + ); + return new GraphAccountTreeItem( + parent, + id, + label, + documentEndpoint, + gremlinEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + } + case "Core": + default: + // Default to DocumentDB, the base type for all Cosmos DB Accounts + return new DocDBAccountTreeItem( + parent, + id, + label, + documentEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + } + } + } + public static async initPostgresChild( + server: PostgresAbstractServer, + parent: AzExtParentTreeItem + ): Promise { + const connectionString: string = createPostgresConnectionString( + nonNullProp(server, "fullyQualifiedDomainName") + ); + const parsedCS: ParsedPostgresConnectionString = + parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(parent, parsedCS, server); + } } diff --git a/Source/utils/InteractiveChildProcess.ts b/Source/utils/InteractiveChildProcess.ts index 26129b342..1cd1848e5 100644 --- a/Source/utils/InteractiveChildProcess.ts +++ b/Source/utils/InteractiveChildProcess.ts @@ -3,174 +3,194 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as cp from 'child_process'; -import * as os from 'os'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { Event, EventEmitter } from 'vscode'; -import { improveError } from './improveError'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as cp from "child_process"; +import * as os from "os"; +import { isNumber } from "util"; +import * as vscode from "vscode"; +import { Event, EventEmitter } from "vscode"; +import { improveError } from "./improveError"; // We add these when we display to the output window -const stdInPrefix = '> '; -const stdErrPrefix = 'ERR> '; -const errorPrefix = 'Error running process: '; +const stdInPrefix = "> "; +const stdErrPrefix = "ERR> "; +const errorPrefix = "Error running process: "; const processStartupTimeout = 60; export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; + command: string; + args: string[]; + outputChannel?: vscode.OutputChannel; + workingDirectory?: string; + showTimeInOutputChannel?: boolean; + outputFilterSearch?: RegExp; + outputFilterReplace?: string; } export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create(options: IInteractiveChildProcessOptions): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess(options); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(' '); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false - }; - - this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); - this._childProc = cp.spawn(this._options.command, this._options.args, options); - - this._childProc.stdout?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on('error', (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on('close', (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel(text: string, displayPrefix?: string): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = (filteredText !== text && filteredText === ''); - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); - } - - return text; - } + private _childProc: cp.ChildProcess; + private readonly _options: IInteractiveChildProcessOptions; + private _startTime: number; + private _error: unknown; + private _isKilling: boolean; + + private readonly _onStdOutEmitter: EventEmitter = + new EventEmitter(); + private readonly _onStdErrEmitter: EventEmitter = + new EventEmitter(); + private readonly _onErrorEmitter: EventEmitter = + new EventEmitter(); + + private constructor(options: IInteractiveChildProcessOptions) { + this._options = options; + } + + public get onStdOut(): Event { + return this._onStdOutEmitter.event; + } + + public get onStdErr(): Event { + return this._onStdErrEmitter.event; + } + + public get onError(): Event { + return this._onErrorEmitter.event; + } + + public static async create( + options: IInteractiveChildProcessOptions + ): Promise { + const child: InteractiveChildProcess = new InteractiveChildProcess( + options + ); + await child.startCore(); + return child; + } + + public kill(): void { + this._isKilling = true; + this._childProc.kill(); + } + + public writeLine(text: string): void { + this.writeLineToOutputChannel(text, stdInPrefix); + this._childProc.stdin?.write(text + os.EOL); + } + + private async startCore(): Promise { + this._startTime = Date.now(); + const formattedArgs: string = this._options.args.join(" "); + + const workingDirectory = this._options.workingDirectory || os.tmpdir(); + const options: cp.SpawnOptions = { + cwd: workingDirectory, + + // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since + // the command is run in the shell, handling errors (such as command not found) would be more indirect, + // coming through STDERR instead of the error event + shell: false, + }; + + this.writeLineToOutputChannel( + `Starting executable: "${this._options.command}" ${formattedArgs}` + ); + this._childProc = cp.spawn( + this._options.command, + this._options.args, + options + ); + + this._childProc.stdout?.on("data", (data: string | Buffer) => { + const text = data.toString(); + this._onStdOutEmitter.fire(text); + this.writeLineToOutputChannel(text); + }); + + this._childProc.stderr?.on("data", (data: string | Buffer) => { + const text = data.toString(); + this._onStdErrEmitter.fire(text); + this.writeLineToOutputChannel(text, stdErrPrefix); + }); + + this._childProc.on("error", (error: unknown) => { + const improvedError = improveError(error); + this.setError(improvedError); + }); + + this._childProc.on("close", (code: number | null) => { + if (isNumber(code) && code !== 0) { + this.setError(`The process exited with code ${code}.`); + } else if (!this._isKilling) { + this.setError(`The process exited prematurely.`); + } + }); + + // Wait for the process to start up + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + await new Promise(async (resolve, reject) => { + const started = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + if (!!this._error || this._isKilling) { + reject(this._error); + break; + } else if (this._childProc.pid) { + resolve(); + break; + } else { + if (Date.now() > started + processStartupTimeout) { + reject("The process did not start in a timely manner"); + break; + } + await delay(50); + } + } + }); + } + + private writeLineToOutputChannel( + text: string, + displayPrefix?: string + ): void { + const filteredText = this.filterText(text); + const changedIntoEmptyString = + filteredText !== text && filteredText === ""; + + if (!changedIntoEmptyString) { + text = filteredText; + if (this._options.outputChannel) { + if (this._options.showTimeInOutputChannel) { + const ms = Date.now() - this._startTime; + text = `${ms}ms: ${text}`; + } + + text = (displayPrefix || "") + text; + this._options.outputChannel.appendLine(text); + } + } + } + + private setError(error: unknown): void { + this.writeLineToOutputChannel(parseError(error).message, errorPrefix); + this._error = this._error || error; + this._onErrorEmitter.fire(error); + } + + private filterText(text: string): string { + if (this._options.outputFilterSearch) { + return text.replace( + this._options.outputFilterSearch, + this._options.outputFilterReplace || "" + ); + } + + return text; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/utils/activityUtils.ts b/Source/utils/activityUtils.ts index fefd2fe00..d90c436cd 100644 --- a/Source/utils/activityUtils.ts +++ b/Source/utils/activityUtils.ts @@ -8,8 +8,13 @@ import { ext } from "../extensionVariables"; import { getWorkspaceSetting } from "./settingUtils"; export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), - }; + return { + registerActivity: async (activity) => + ext.rgApi.registerActivity(activity), + suppressNotification: await getWorkspaceSetting( + "suppressActivityNotifications", + undefined, + "azureResourceGroups" + ), + }; } diff --git a/Source/utils/array.ts b/Source/utils/array.ts index 06f095e8d..5d779a53a 100644 --- a/Source/utils/array.ts +++ b/Source/utils/array.ts @@ -4,11 +4,21 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { - return arr ? arr.filter(element => element instanceof genericConstructor) : []; +export function filterType( + arr: Object[] | undefined, + genericConstructor: new (...args: any[]) => T +): T[] { + return arr + ? arr.filter((element) => element instanceof genericConstructor) + : []; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { - return arr && arr.find(element => element instanceof genericConstructor); +export function findType( + arr: Object[] | undefined, + genericConstructor: new (...args: any[]) => T +): T | undefined { + return ( + arr && arr.find((element) => element instanceof genericConstructor) + ); } diff --git a/Source/utils/azureClients.ts b/Source/utils/azureClients.ts index 9be19e959..c2f44bd1c 100644 --- a/Source/utils/azureClients.ts +++ b/Source/utils/azureClients.ts @@ -3,22 +3,41 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; -import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { PostgreSQLManagementClient } from "@azure/arm-postgresql"; +import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; +import { + AzExtClientContext, + createAzureClient, +} from "@microsoft/vscode-azext-azureutils"; // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript -export async function createCosmosDBClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); +export async function createCosmosDBClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-cosmosdb")).CosmosDBManagementClient + ); } -export async function createPostgreSQLClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); +export async function createPostgreSQLClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-postgresql")).PostgreSQLManagementClient + ); } -export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); +export async function createPostgreSQLFlexibleClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-postgresql-flexible")) + .PostgreSQLManagementClient + ); } diff --git a/Source/utils/azureUtils.ts b/Source/utils/azureUtils.ts index b0017314b..0e067aa68 100644 --- a/Source/utils/azureUtils.ts +++ b/Source/utils/azureUtils.ts @@ -4,11 +4,13 @@ *--------------------------------------------------------------------------------------------*/ export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); + const matches: RegExpMatchArray | null = id.match( + /\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/ + ); - if (!matches || matches.length < 5) { - throw new Error('Invalid Azure Resource Id'); - } + if (!matches || matches.length < 5) { + throw new Error("Invalid Azure Resource Id"); + } - return matches[4]; + return matches[4]; } diff --git a/Source/utils/cp.ts b/Source/utils/cp.ts index 660dc3068..7f7d94117 100644 --- a/Source/utils/cp.ts +++ b/Source/utils/cp.ts @@ -3,12 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from 'child_process'; +import * as cp from "child_process"; -export async function commandSucceeds(command: string, ...args: string[]): Promise { - return await new Promise(resolve => { - cp.spawn(command, args) - .on('error', _error => resolve(false)) - .on('exit', code => resolve(code === 0)); - }); +export async function commandSucceeds( + command: string, + ...args: string[] +): Promise { + return await new Promise((resolve) => { + cp.spawn(command, args) + .on("error", (_error) => resolve(false)) + .on("exit", (code) => resolve(code === 0)); + }); } diff --git a/Source/utils/getIp.ts b/Source/utils/getIp.ts index 20d22e989..d3085ea52 100644 --- a/Source/utils/getIp.ts +++ b/Source/utils/getIp.ts @@ -1,61 +1,73 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { isIPv4 } from 'net'; -import { localize } from './localize'; - -export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { sendRequestWithTimeout } from "@microsoft/vscode-azext-azureutils"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { isIPv4 } from "net"; +import { localize } from "./localize"; + +export function isIpInRanges( + ip: string, + ranges: { startIpAddress: string; endIpAddress: string }[] +): boolean { + const ipNum = ipToNum(ip); + return ranges.some((range) => { + const startIpNum = ipToNum(range.startIpAddress); + const endIpNum = ipToNum(range.endIpAddress); + return startIpNum <= ipNum && ipNum <= endIpNum; + }); } export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, 'https://api.ipify.org/'), - () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; + const methods: (() => Promise)[] = [ + () => getPublicIpv4Https(context, "https://api.ipify.org/"), + () => getPublicIpv4Https(context, "https://ipv4.icanhazip.com/"), + ]; + + let lastError: unknown; + for (const getIp of methods) { + try { + return await getIp(); + } catch (e: unknown) { + lastError = e; + } + } + + throw lastError; } -const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); +const failedToGetIp = localize("failedToGetIp", "Failed to get public IP"); function ipToNum(ip: string) { - return Number( - ip.split(".") - .map(d => ("000" + d).substring(-3)) - .join("") - ); + return Number( + ip + .split(".") + .map((d) => ("000" + d).substring(-3)) + .join("") + ); } -async function getPublicIpv4Https(context: IActionContext, url: string): Promise { - const req = await sendRequestWithTimeout(context, { - method: 'GET', - url, - }, 5000, undefined); +async function getPublicIpv4Https( + context: IActionContext, + url: string +): Promise { + const req = await sendRequestWithTimeout( + context, + { + method: "GET", + url, + }, + 5000, + undefined + ); - const ip = req.bodyAsText; + const ip = req.bodyAsText; - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } + if (!ip || !isIPv4(ip)) { + throw new Error(failedToGetIp); + } - return ip; + return ip; } diff --git a/Source/utils/getSecretStorageKey.ts b/Source/utils/getSecretStorageKey.ts index 8e404f554..d04de6cea 100644 --- a/Source/utils/getSecretStorageKey.ts +++ b/Source/utils/getSecretStorageKey.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; + return `${serviceName}.${id}`; } diff --git a/Source/utils/improveError.ts b/Source/utils/improveError.ts index 27ff1f014..08f0bedaf 100644 --- a/Source/utils/improveError.ts +++ b/Source/utils/improveError.ts @@ -6,12 +6,12 @@ import { parseError } from "@microsoft/vscode-azext-utils"; export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } + const message = parseError(error).message; + // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" + const match = message.match(/spawn (.*) ENOENT/); + if (match) { + return new Error(`Could not find ${match[1]}`); + } - return error; + return error; } diff --git a/Source/utils/localize.ts b/Source/utils/localize.ts index 2aee3fa12..76d8fbf4d 100644 --- a/Source/utils/localize.ts +++ b/Source/utils/localize.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vscode-nls'; +import * as nls from "vscode-nls"; export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Source/utils/nonNull.ts b/Source/utils/nonNull.ts index d7104b4f8..e9437afc9 100644 --- a/Source/utils/nonNull.ts +++ b/Source/utils/nonNull.ts @@ -3,39 +3,52 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { isNullOrUndefined } from 'util'; +import { isNullOrUndefined } from "util"; /** * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed * for the property and will give a compile error if the given name is not a property of the source. */ -export function nonNullProp(source: TSource, name: TKey): NonNullable { - const value: NonNullable = >source[name]; - return nonNullValue(value, name); +export function nonNullProp( + source: TSource, + name: TKey +): NonNullable { + const value: NonNullable = >( + source[name] + ); + return nonNullValue(value, name); } /** * Validates that a given value is not null and not undefined. */ -export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { - if (isNullOrUndefined(value)) { - throw new Error( - 'Internal error: Expected value to be neither null nor undefined' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } +export function nonNullValue( + value: T | undefined | null, + propertyNameOrMessage?: string +): T { + if (isNullOrUndefined(value)) { + throw new Error( + "Internal error: Expected value to be neither null nor undefined" + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") + ); + } - return value; + return value; } /** * Validates that a given string is not null, undefined, nor empty */ -export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { - if (!value) { - throw new Error( - 'Internal error: Expected value to be neither null, undefined, nor empty' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } +export function nonNullOrEmptyValue( + value: string | undefined, + propertyNameOrMessage?: string +): string { + if (!value) { + throw new Error( + "Internal error: Expected value to be neither null, undefined, nor empty" + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") + ); + } - return value; + return value; } diff --git a/Source/utils/openUrl.ts b/Source/utils/openUrl.ts index 0be3f5bbb..5c7deaca7 100644 --- a/Source/utils/openUrl.ts +++ b/Source/utils/openUrl.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as open from 'open'; +import * as open from "open"; export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); + // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 + // await vscode.env.openExternal(vscode.Uri.parse(url)); - await open(url); + await open(url); } diff --git a/Source/utils/randomUtils.ts b/Source/utils/randomUtils.ts index 7a313f23a..1c4856b09 100644 --- a/Source/utils/randomUtils.ts +++ b/Source/utils/randomUtils.ts @@ -6,12 +6,15 @@ import * as crypto from "crypto"; export namespace randomUtils { - export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { - return crypto.createHash('sha256').update(s).digest(encoding); - } + export function getPseudononymousStringHash( + s: string, + encoding: crypto.BinaryToTextEncoding = "base64" + ): string { + return crypto.createHash("sha256").update(s).digest(encoding); + } - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString('hex').slice(0, length); - } + export function getRandomHexString(length: number): string { + const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); + return buffer.toString("hex").slice(0, length); + } } diff --git a/Source/utils/settingUtils.ts b/Source/utils/settingUtils.ts index 0ac1004c2..0f75feb17 100644 --- a/Source/utils/settingUtils.ts +++ b/Source/utils/settingUtils.ts @@ -3,60 +3,98 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; +import { + ConfigurationTarget, + Uri, + workspace, + WorkspaceConfiguration, +} from "vscode"; import { ext } from "../extensionVariables"; /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - await projectConfiguration.update(section, value, ConfigurationTarget.Global); +export async function updateGlobalSetting( + section: string, + value: T, + prefix: string = ext.prefix +): Promise { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix); + await projectConfiguration.update( + section, + value, + ConfigurationTarget.Global + ); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); +export async function updateWorkspaceSetting( + section: string, + value: T, + fsPath: string, + prefix: string = ext.prefix +): Promise { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix, Uri.file(fsPath)); + await projectConfiguration.update(section, value); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); - return result && result.globalValue; +export function getGlobalSetting( + key: string, + prefix: string = ext.prefix +): T | undefined { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix); + const result: { globalValue?: T } | undefined = + projectConfiguration.inspect(key); + return result && result.globalValue; } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); - return projectConfiguration.get(key); +export function getWorkspaceSetting( + key: string, + fsPath?: string, + prefix: string = ext.prefix +): T | undefined { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration( + prefix, + fsPath ? Uri.file(fsPath) : undefined + ); + return projectConfiguration.get(key); } /** * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } +export function getWorkspaceSettingFromAnyFolder( + key: string, + prefix: string = ext.prefix +): string | undefined { + if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { + let result: string | undefined; + for (const folder of workspace.workspaceFolders) { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix, folder.uri); + const folderResult: string | undefined = + projectConfiguration.get(key); + if (!result) { + result = folderResult; + } else if (folderResult && result !== folderResult) { + return undefined; + } + } + return result; + } else { + return getGlobalSetting(key, prefix); + } } diff --git a/Source/utils/timeout.ts b/Source/utils/timeout.ts index cc5ffb2d6..1645f6d3f 100644 --- a/Source/utils/timeout.ts +++ b/Source/utils/timeout.ts @@ -8,44 +8,50 @@ const timedOutMessage = "Execution timed out"; /** * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. */ -export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } +export async function valueOnTimeout( + timeoutMs: number, + timeoutValue: T, + action: () => Promise | T +): Promise { + try { + return await rejectOnTimeout(timeoutMs, action); + } catch (err) { + const error = <{ message?: string }>err; + if (error && error.message === timedOutMessage) { + return timeoutValue; + } - throw err; - } + throw err; + } } /** * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. */ -export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout( - () => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, - timeoutMs); +export async function rejectOnTimeout( + timeoutMs: number, + action: () => Promise | T, + callerTimeOutMessage?: string +): Promise { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + return await new Promise(async (resolve, reject) => { + let timer: NodeJS.Timer | undefined = setTimeout(() => { + timer = undefined; + reject(new Error(callerTimeOutMessage || timedOutMessage)); + }, timeoutMs); - let value: T; - let error; + let value: T; + let error; - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); + try { + value = await action(); + clearTimeout(timer); + resolve(value); + } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + error = err; + clearTimeout(timer); + reject(error); + } + }); } diff --git a/Source/utils/vscodeUtils.ts b/Source/utils/vscodeUtils.ts index d05f84872..bdb5665b5 100644 --- a/Source/utils/vscodeUtils.ts +++ b/Source/utils/vscodeUtils.ts @@ -3,101 +3,145 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from '@azure/cosmos'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; -import { getRootPath } from './workspacUtils'; +import { ItemDefinition } from "@azure/cosmos"; +import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import * as path from "path"; +import * as vscode from "vscode"; +import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../extensionVariables"; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { IMongoDocument } from "../mongo/tree/MongoDocumentTreeItem"; +import { getRootPath } from "./workspacUtils"; export interface IDisposable { - dispose(): void; + dispose(): void; } export function dispose(disposables: T[]): T[] { - disposables.forEach(d => d.dispose()); - return []; + disposables.forEach((d) => d.dispose()); + return []; } export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; + return { dispose }; } -export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); - const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); - await writeToEditor(editor, data); +export async function showNewFile( + data: string, + fileName: string, + fileExtension: string, + column?: vscode.ViewColumn +): Promise { + const folderPath: string = getRootPath() || ext.context.extensionPath; + const fullFileName: string | undefined = await getUniqueFileName( + folderPath, + fileName, + fileExtension + ); + const uri: vscode.Uri = vscode.Uri.file( + path.join(folderPath, fullFileName) + ).with({ scheme: "untitled" }); + const textDocument = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument( + textDocument, + column + ? column > vscode.ViewColumn.Three + ? vscode.ViewColumn.One + : column + : undefined, + true + ); + await writeToEditor(editor, data); } -export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt(editor.document.lineCount - 1); - editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); - } +export async function writeToEditor( + editor: vscode.TextEditor, + data: string +): Promise { + await editor.edit((editBuilder: vscode.TextEditorEdit) => { + if (editor.document.lineCount > 0) { + const lastLine = editor.document.lineAt( + editor.document.lineCount - 1 + ); + editBuilder.delete( + new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position( + lastLine.range.start.line, + lastLine.range.end.character + ) + ) + ); + } - editBuilder.insert(new vscode.Position(0, 0), data); - }); + editBuilder.insert(new vscode.Position(0, 0), data); + }); } -async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { - let count: number = 1; - const maxCount: number = 1024; +async function getUniqueFileName( + folderPath: string, + fileName: string, + fileExtension: string +): Promise { + let count: number = 1; + const maxCount: number = 1024; - while (count < maxCount) { - const fileSuffix = count === 0 ? '' : '-' + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; + while (count < maxCount) { + const fileSuffix = count === 0 ? "" : "-" + count.toString(); + const fullFileName: string = fileName + fileSuffix + fileExtension; - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } + const fullPath: string = path.join(folderPath, fullFileName); + const pathExists: boolean = await fse.pathExists(fullPath); + const editorExists: boolean = + vscode.workspace.textDocuments.find( + (doc) => doc.uri.fsPath === fullPath + ) !== undefined; + if (!pathExists && !editorExists) { + return fullFileName; + } + count += 1; + } - throw new Error('Could not find unique name for new file.'); + throw new Error("Could not find unique name for new file."); } export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join('/'); + const labels = [node.label]; + while (node.parent) { + node = node.parent; + labels.unshift(node.label); + if (isAccountTreeItem(node)) { + break; + } + } + return labels.join("/"); } function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); + return ( + treeItem instanceof MongoAccountTreeItem || + treeItem instanceof DocDBAccountTreeItemBase + ); } -export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== 'object') { - return String(value); - } - } - } - return String(document._id); +export function getDocumentTreeItemLabel( + document: IMongoDocument | ItemDefinition +): string { + for (const field of getDocumentLabelFields()) { + // eslint-disable-next-line no-prototype-builtins + if (document.hasOwnProperty(field)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const value = document[field]; + if (value !== undefined && typeof value !== "object") { + return String(value); + } + } + } + return String(document._id); } function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; + const settingKey: string = ext.settingsKeys.documentLabelFields; + return vscode.workspace.getConfiguration().get(settingKey) || []; } diff --git a/Source/utils/workspacUtils.ts b/Source/utils/workspacUtils.ts index 20b60da11..6892c2f6d 100644 --- a/Source/utils/workspacUtils.ts +++ b/Source/utils/workspacUtils.ts @@ -3,16 +3,23 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { nonNullValue } from './nonNull'; +import * as vscode from "vscode"; +import { ext } from "../extensionVariables"; +import { nonNullValue } from "./nonNull"; export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; + // if this is a multi-root workspace, return undefined + return vscode.workspace.workspaceFolders && + vscode.workspace.workspaceFolders.length === 1 + ? vscode.workspace.workspaceFolders[0].uri.fsPath + : undefined; } export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); + const config: vscode.WorkspaceConfiguration = + vscode.workspace.getConfiguration(); + return nonNullValue( + config.get(ext.settingsKeys.batchSize), + "batchSize" + ); } diff --git a/Source/utils/wrapError.ts b/Source/utils/wrapError.ts index f6ec5d2b5..b82f638fd 100644 --- a/Source/utils/wrapError.ts +++ b/Source/utils/wrapError.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; +import * as os from "os"; export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } + if (!innerError) { + return outerError; + } else if (!outerError) { + return innerError; + } - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } + const innerMessage = parseError(innerError).message; + const outerMessage = parseError(outerError).message; + if (outerError instanceof Error) { + outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; + return outerError; + } - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); + return new Error(`${outerMessage}${os.EOL}${innerMessage}`); } diff --git a/Source/vscode-cosmosdb.api.d.ts b/Source/vscode-cosmosdb.api.d.ts index d5e4416c1..4e813c5e5 100644 --- a/Source/vscode-cosmosdb.api.d.ts +++ b/Source/vscode-cosmosdb.api.d.ts @@ -4,93 +4,103 @@ *--------------------------------------------------------------------------------------------*/ export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem(query: TreeItemQuery): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; + apiVersion: string; + + /** + * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. + * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. + * + * @param query The query object to use for the find + */ + findTreeItem( + query: TreeItemQuery + ): Promise; + + /** + * Prompts the user to pick an item from the Azure Databases tree + * + * @param options Configures the behavior of the tree item picker + */ + pickTreeItem( + options: PickTreeItemOptions & { resourceType: "DatabaseAccount" } + ): Promise; + pickTreeItem( + options: PickTreeItemOptions & { resourceType: "Database" } + ): Promise; + + /** + * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string + */ + revealTreeItem(resourceId: string): Promise; } export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; + /** + * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. + */ + reveal(): Promise; } export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - } - - docDBData?: { - masterKey: string; - documentEndpoint: string; - } - - postgresData?: { - username: string | undefined; - password: string | undefined; - } - + hostName: string; + port: string; + connectionString: string; + + /** + * Data specific to Azure or undefined if the resource is not in Azure. + */ + azureData?: { + accountName: string; + accountId: string; + }; + + docDBData?: { + masterKey: string; + documentEndpoint: string; + }; + + postgresData?: { + username: string | undefined; + password: string | undefined; + }; } export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; + databaseName: string; } -export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; +export type AzureDatabasesResourceType = "DatabaseAccount" | "Database"; -export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; +export type AzureDatabasesApiType = + | "Mongo" + | "SQL" + | "Graph" + | "Table" + | "Postgres"; export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; + /** + * The resource type of the picked item + */ + resourceType: AzureDatabasesResourceType; + + /** + * An array of the API types that can be picked, or undefined if all API types are allowed + */ + apiType?: AzureDatabasesApiType[]; } export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - } + /** + * An account or database connection string + */ + connectionString?: string; + + postgresData?: { + hostName: string; + port: string; + databaseName: string | undefined; + username: string | undefined; + password: string | undefined; + }; } diff --git a/Source/vscode-cosmosdbgraph.api.d.ts b/Source/vscode-cosmosdbgraph.api.d.ts index 95cde2531..bf8d4c769 100644 --- a/Source/vscode-cosmosdbgraph.api.d.ts +++ b/Source/vscode-cosmosdbgraph.api.d.ts @@ -4,26 +4,26 @@ *--------------------------------------------------------------------------------------------*/ export interface CosmosDBGraphExtensionApi { - apiVersion: string; + apiVersion: string; - openGraphExplorer(config: IGraphConfiguration): Promise; + openGraphExplorer(config: IGraphConfiguration): Promise; } export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; + host: string; + port: number; + ssl: boolean; } export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; + // e.g. https://graphaccount.documents.azure.com:443 + documentEndpoint: string; - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; + gremlinEndpoint?: IGremlinEndpoint; + possibleGremlinEndpoints: IGremlinEndpoint[]; - key: string; - databaseName: string; - graphName: string; - tabTitle: string; + key: string; + databaseName: string; + graphName: string; + tabTitle: string; } diff --git a/build/vscode-languageserver-files-stub.js b/build/vscode-languageserver-files-stub.js index b7e70019f..568f06348 100644 --- a/build/vscode-languageserver-files-stub.js +++ b/build/vscode-languageserver-files-stub.js @@ -10,7 +10,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const url = require("url"); const path = require("path"); @@ -21,25 +21,25 @@ const child_process_1 = require("child_process"); * complete implementation of handling VS Code URIs. */ function uriToFilePath(uri) { - let parsed = url.parse(uri); - if (parsed.protocol !== 'file:' || !parsed.path) { - return undefined; - } - let segments = parsed.path.split('/'); - for (var i = 0, len = segments.length; i < len; i++) { - segments[i] = decodeURIComponent(segments[i]); - } - if (process.platform === 'win32' && segments.length > 1) { - let first = segments[0]; - let second = segments[1]; - // Do we have a drive letter and we started with a / which is the - // case if the first segement is empty (see split above) - if (first.length === 0 && second.length > 1 && second[1] === ':') { - // Remove first slash - segments.shift(); - } - } - return path.normalize(segments.join('/')); + let parsed = url.parse(uri); + if (parsed.protocol !== "file:" || !parsed.path) { + return undefined; + } + let segments = parsed.path.split("/"); + for (var i = 0, len = segments.length; i < len; i++) { + segments[i] = decodeURIComponent(segments[i]); + } + if (process.platform === "win32" && segments.length > 1) { + let first = segments[0]; + let second = segments[1]; + // Do we have a drive letter and we started with a / which is the + // case if the first segement is empty (see split above) + if (first.length === 0 && second.length > 1 && second[1] === ":") { + // Remove first slash + segments.shift(); + } + } + return path.normalize(segments.join("/")); } exports.uriToFilePath = uriToFilePath; @@ -47,26 +47,26 @@ exports.uriToFilePath = uriToFilePath; // Throw NYI if any of the other functions are ever called (they shouldn't be currently) function resolveModule(workspaceRoot, moduleName) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModule = resolveModule; function resolve(moduleName, nodePath, cwd, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolve = resolve; function resolveGlobalNodePath(tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveGlobalNodePath = resolveGlobalNodePath; function resolveGlobalYarnPath(tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveGlobalYarnPath = resolveGlobalYarnPath; function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModulePath = resolveModulePath; function resolveModule2(workspaceRoot, moduleName, nodePath, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModule2 = resolveModule2; diff --git a/extension.bundle.ts b/extension.bundle.ts index 0cd4aff0d..aef525815 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -12,38 +12,66 @@ // Export activate/deactivate for main.js // The tests use instanceof against these and therefore we need to make sure we're using the same version of the bson module in the tests as in the bundle, // so export it from the bundle itself. -export { ObjectID, ObjectId } from 'bson'; +export { ObjectID, ObjectId } from "bson"; // Exports for tests // The tests are not packaged with the webpack bundle and therefore only have access to code exported from this file. // // The tests should import '../extension.bundle.ts'. At design-time they live in tests/ and so will pick up this file (extension.bundle.ts). // At runtime the tests live in dist/tests and will therefore pick up the main webpack bundle at dist/extension.bundle.js. -export { AzureAccountTreeItemBase, createAzureClient } from '@microsoft/vscode-azext-azureutils'; -export * from '@microsoft/vscode-azext-utils'; -export { emulatorPassword, isWindows } from './src/constants'; -export { ParsedDocDBConnectionString, parseDocDBConnectionString } from './src/docdb/docDBConnectionStrings'; -export { getCosmosClient } from './src/docdb/getCosmosClient'; -export * from './src/docdb/registerDocDBCommands'; -export { activateInternal, cosmosDBCopyConnectionString, createServer, deactivateInternal, deleteAccount } from './src/extension'; -export { ext } from './src/extensionVariables'; -export * from './src/graph/registerGraphCommands'; -export { connectToMongoClient, isCosmosEmulatorConnectionString } from './src/mongo/connectToMongoClient'; -export { MongoCommand } from './src/mongo/MongoCommand'; -export { addDatabaseToAccountConnectionString, encodeMongoConnectionString, getDatabaseNameFromConnectionString } from './src/mongo/mongoConnectionStrings'; -export { findCommandAtPosition, getAllCommandsFromText } from './src/mongo/MongoScrapbook'; -export { MongoShell } from './src/mongo/MongoShell'; -export * from './src/mongo/registerMongoCommands'; -export { IDatabaseInfo } from './src/mongo/tree/MongoAccountTreeItem'; -export { addDatabaseToConnectionString } from './src/postgres/postgresConnectionStrings'; -export { AttachedAccountsTreeItem, MONGO_CONNECTION_EXPECTED } from './src/tree/AttachedAccountsTreeItem'; -export { AzureAccountTreeItemWithAttached } from './src/tree/AzureAccountTreeItemWithAttached'; -export * from './src/utils/azureClients'; -export { improveError } from './src/utils/improveError'; -export { randomUtils } from './src/utils/randomUtils'; -export { getGlobalSetting, updateGlobalSetting } from './src/utils/settingUtils'; -export { rejectOnTimeout, valueOnTimeout } from './src/utils/timeout'; -export { getDocumentTreeItemLabel, IDisposable } from './src/utils/vscodeUtils'; -export { wrapError } from './src/utils/wrapError'; -export { isIpInRanges, getPublicIpv4 } from './src/utils/getIp' +export { + AzureAccountTreeItemBase, + createAzureClient, +} from "@microsoft/vscode-azext-azureutils"; +export * from "@microsoft/vscode-azext-utils"; +export { emulatorPassword, isWindows } from "./src/constants"; +export { + ParsedDocDBConnectionString, + parseDocDBConnectionString, +} from "./src/docdb/docDBConnectionStrings"; +export { getCosmosClient } from "./src/docdb/getCosmosClient"; +export * from "./src/docdb/registerDocDBCommands"; +export { + activateInternal, + cosmosDBCopyConnectionString, + createServer, + deactivateInternal, + deleteAccount, +} from "./src/extension"; +export { ext } from "./src/extensionVariables"; +export * from "./src/graph/registerGraphCommands"; +export { + connectToMongoClient, + isCosmosEmulatorConnectionString, +} from "./src/mongo/connectToMongoClient"; +export { MongoCommand } from "./src/mongo/MongoCommand"; +export { + addDatabaseToAccountConnectionString, + encodeMongoConnectionString, + getDatabaseNameFromConnectionString, +} from "./src/mongo/mongoConnectionStrings"; +export { + findCommandAtPosition, + getAllCommandsFromText, +} from "./src/mongo/MongoScrapbook"; +export { MongoShell } from "./src/mongo/MongoShell"; +export * from "./src/mongo/registerMongoCommands"; +export { IDatabaseInfo } from "./src/mongo/tree/MongoAccountTreeItem"; +export { addDatabaseToConnectionString } from "./src/postgres/postgresConnectionStrings"; +export { + AttachedAccountsTreeItem, + MONGO_CONNECTION_EXPECTED, +} from "./src/tree/AttachedAccountsTreeItem"; +export { AzureAccountTreeItemWithAttached } from "./src/tree/AzureAccountTreeItemWithAttached"; +export * from "./src/utils/azureClients"; +export { improveError } from "./src/utils/improveError"; +export { randomUtils } from "./src/utils/randomUtils"; +export { + getGlobalSetting, + updateGlobalSetting, +} from "./src/utils/settingUtils"; +export { rejectOnTimeout, valueOnTimeout } from "./src/utils/timeout"; +export { getDocumentTreeItemLabel, IDisposable } from "./src/utils/vscodeUtils"; +export { wrapError } from "./src/utils/wrapError"; +export { isIpInRanges, getPublicIpv4 } from "./src/utils/getIp"; // NOTE: The auto-fix action "source.organizeImports" does weird things with this file, but there doesn't seem to be a way to disable it on a per-file basis so we'll just let it happen diff --git a/grammar/JavaScript.tmLanguage.json b/grammar/JavaScript.tmLanguage.json index 71207a7b3..4928616c4 100644 --- a/grammar/JavaScript.tmLanguage.json +++ b/grammar/JavaScript.tmLanguage.json @@ -1,3713 +1,3711 @@ { - "name.$comment": "** Changed **", - "name": "Mongo Scrapbooks (JavaScript)", - "scopeName.$comment": "** Changed **", - "scopeName": "source.mongo.js", - "fileTypes.$comment": "** Changed from .js/.jsx **", - "fileTypes": [ - ".mongo" - ], - "uuid.$comment": "** Changed **", - "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", - "patterns": [ - { - "include": "#directives" - }, - { - "include": "#statements" - }, - { - "name": "comment.line.shebang.ts", - "match": "\\A(#!).*(?=$)", - "captures": { - "1": { - "name": "punctuation.definition.comment.ts" - } - } - } - ], - "repository": { - "statements": { - "patterns": [ - { - "include": "#string" - }, - { - "include": "#template" - }, - { - "include": "#comment" - }, - { - "include": "#declaration" - }, - { - "include": "#switch-statement" - }, - { - "include": "#for-loop" - }, - { - "include": "#after-operator-block" - }, - { - "include": "#decl-block" - }, - { - "include": "#control-statement" - }, - { - "include": "#expression" - }, - { - "include": "#punctuation-semicolon" - } - ] - }, - "var-expr": { - "name": "meta.var.expr.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js entity.name.function.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.constant.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.readwrite.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - } - ] - }, - "var-single-variable-type-annotation": { - "patterns": [ - { - "include": "#type-annotation" - }, - { - "include": "#string" - }, - { - "include": "#comment" - } - ] - }, - "destructuring-variable": { - "patterns": [ - { - "name": "meta.object-binding-pattern-variable.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" - }, - { - "name": "meta.definition.property.js variable.object.property.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.js", - "match": "\\?" - } - ] - } - ] - }, - "method-declaration": { - "name": "meta.method.declaration.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "captures": { - "1": { - "name": "storage.modifier.js" - }, - "2": { - "name": "keyword.operator.rest.js" - }, - "3": { - "name": "entity.name.function.js" - }, - "4": { - "name": "keyword.operator.optional.js" - } - } - }, - { - "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type" - } - ] - }, - "type": { - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#string" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#type-primitive" - }, - { - "include": "#type-builtin-literals" - }, - { - "include": "#type-parameters" - }, - { - "include": "#type-tuple" - }, - { - "include": "#type-object" - }, - { - "include": "#type-operators" - }, - { - "include": "#type-fn-type-parameters" - }, - { - "include": "#type-paren-or-function-parameters" - }, - { - "include": "#type-function-return-type" - }, - { - "include": "#type-name" - } - ] - }, - "function-parameters": { - "name": "meta.parameters.js", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#decorator" - }, - { - "include": "#destructuring-parameter" - }, - { - "include": "#parameter-name" - }, - { - "include": "#type-annotation" - }, - { - "include": "#variable-initializer" - }, - { - "name": "punctuation.separator.parameter.js", - "match": "," - } - ] - }, - "type-primitive": { - "name": "support.type.primitive.js", - "match": "(?)\n ))\n )\n )\n)", - "end": "(?<=\\))", - "patterns": [ - { - "include": "#function-parameters" - } - ] - } - ] - }, - "type-operators": { - "patterns": [ - { - "include": "#typeof-operator" - }, - { - "name": "keyword.operator.type.js", - "match": "[&|]" - }, - { - "name": "keyword.operator.expression.keyof.js", - "match": "(?", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", - "patterns": [ - { - "include": "#comment" - }, - { - "name": "meta.object.type.js", - "begin": "(?<==>)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "type-tuple": { - "name": "meta.type.tuple.js", - "begin": "\\[", - "beginCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "type-name": { - "patterns": [ - { - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", - "captures": { - "1": { - "name": "entity.name.type.module.js" - }, - "2": { - "name": "punctuation.accessor.js" - } - } - }, - { - "name": "entity.name.type.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "type-parameters": { - "name": "meta.type.parameters.js", - "begin": "(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "(?=$)|(>)", - "endCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "name": "storage.modifier.js", - "match": "(?)" - }, - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "variable-initializer": { - "patterns": [ - { - "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "support.constant.dom.js" - }, - "3": { - "name": "support.variable.property.dom.js" - } - } - }, - { - "name": "support.class.node.js", - "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", - "patterns": [ - { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "entity.name.function.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - }, - { - "include": "#comment" - }, - { - "name": "meta.type.parameters.js", - "begin": "\\<", - "beginCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "\\>", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - { - "include": "#paren-expression" - } - ] - }, - "identifiers": { - "patterns": [ - { - "include": "#object-identifiers" - }, - { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "entity.name.function.js" - } - } - }, - { - "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.property.js" - } - } - }, - { - "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.property.js" - } - } - }, - { - "name": "variable.other.constant.js", - "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" - }, - { - "name": "variable.other.readwrite.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "object-identifiers": { - "patterns": [ - { - "name": "support.class.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" - }, - { - "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.object.property.js" - }, - "3": { - "name": "variable.other.object.property.js" - } - } - }, - { - "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "variable.other.constant.object.js" - }, - "2": { - "name": "variable.other.object.js" - } - } - } - ] - }, - "cast": { - "patterns": [ - { - "include": "#jsx" - } - ] - }, - "new-expr": { - "name": "new.expr.js", - "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "entity.name.function.js" - }, - "2": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "\\.\\.\\.", - "beginCaptures": { - "0": { - "name": "keyword.operator.spread.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", - "captures": { - "1": { - "name": "variable.other.readwrite.js" - } - } - }, - { - "include": "#punctuation-comma" - } - ] - }, - "expression-operators": { - "patterns": [ - { - "name": "keyword.control.flow.js", - "match": "(?>=|>>>=|\\|=" - }, - { - "name": "keyword.operator.bitwise.shift.js", - "match": "<<|>>>|>>" - }, - { - "name": "keyword.operator.comparison.js", - "match": "===|!==|==|!=" - }, - { - "name": "keyword.operator.relational.js", - "match": "<=|>=|<>|<|>" - }, - { - "name": "keyword.operator.logical.js", - "match": "\\!|&&|\\|\\|" - }, - { - "name": "keyword.operator.bitwise.js", - "match": "\\&|~|\\^|\\|" - }, - { - "name": "keyword.operator.assignment.js", - "match": "\\=" - }, - { - "name": "keyword.operator.decrement.js", - "match": "--" - }, - { - "name": "keyword.operator.increment.js", - "match": "\\+\\+" - }, - { - "name": "keyword.operator.arithmetic.js", - "match": "%|\\*|/|-|\\+" - }, - { - "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", - "captures": { - "1": { - "name": "keyword.operator.arithmetic.js" - } - } - } - ] - }, - "typeof-operator": { - "name": "keyword.operator.expression.typeof.js", - "match": "(?)", - "captures": { - "1": { - "name": "storage.modifier.async.js" - }, - "2": { - "name": "variable.parameter.js" - } - } - }, - { - "name": "meta.arrow.js", - "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type-parameters" - }, - { - "include": "#function-parameters" - }, - { - "include": "#arrow-return-type" - } - ] - }, - { - "name": "meta.arrow.js", - "begin": "=>", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?<=\\})|((?!\\{)(?=\\S))", - "patterns": [ - { - "include": "#decl-block" - }, - { - "include": "#expression" - } - ] - } - ] - }, - "arrow-return-type": { - "name": "meta.return.type.arrow.js", - "begin": "(?<=\\))\\s*(:)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "name": "meta.object.type.js", - "begin": "(?<=:)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "punctuation-comma": { - "name": "punctuation.separator.comma.js", - "match": "," - }, - "punctuation-semicolon": { - "name": "punctuation.terminator.statement.js", - "match": ";" - }, - "punctuation-accessor": { - "name": "punctuation.accessor.js", - "match": "\\." - }, - "paren-expression": { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "patterns": [ - { - "include": "#expression" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "qstring-double": { - "name": "string.quoted.double.js", - "begin": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\")|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "qstring-single": { - "name": "string.quoted.single.js", - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\\')|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "regex": { - "patterns": [ - { - "name": "string.regexp.js", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(/)([gimuy]*)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "keyword.other.js" - } - }, - "patterns": [ - { - "include": "#regexp" - } - ] - }, - { - "name": "string.regexp.js", - "begin": "(?\\s*$)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.js" - } - }, - "end": "(?=$)", - "patterns": [ - { - "name": "meta.tag.js", - "begin": "(<)(reference|amd-dependency|amd-module)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.directive.js" - }, - "2": { - "name": "entity.name.tag.directive.js" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.directive.js" - } - }, - "patterns": [ - { - "name": "entity.other.attribute-name.directive.js", - "match": "path|types|no-default-lib|name" - }, - { - "name": "keyword.operator.assignment.js", - "match": "=" - }, - { - "include": "#string" - } - ] - } - ] - }, - "docblock": { - "patterns": [ - { - "name": "storage.type.class.jsdoc", - "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "variable.other.jsdoc" - }, - "3": { - "name": "other.description.jsdoc" - } - } - }, - { - "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "other.description.jsdoc" - } - } - } - ] - }, - "jsx-tag-attributes": { - "patterns": [ - { - "include": "#jsx-tag-attribute-name" - }, - { - "include": "#jsx-tag-attribute-assignment" - }, - { - "include": "#jsx-string-double-quoted" - }, - { - "include": "#jsx-string-single-quoted" - }, - { - "include": "#jsx-evaluated-code" - } - ] - }, - "jsx-tag-attribute-name": { - "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", - "captures": { - "1": { - "name": "entity.other.attribute-name.js" - } - } - }, - "jsx-tag-attribute-assignment": { - "name": "keyword.operator.assignment.js", - "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" - }, - "jsx-string-double-quoted": { - "name": "string.quoted.double.js", - "begin": "\"", - "end": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-string-single-quoted": { - "name": "string.quoted.single.js", - "begin": "'", - "end": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-entities": { - "patterns": [ - { - "name": "constant.character.entity.js", - "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", - "captures": { - "1": { - "name": "punctuation.definition.entity.js" - }, - "3": { - "name": "punctuation.definition.entity.js" - } - } - }, - { - "name": "invalid.illegal.bad-ampersand.js", - "match": "&" - } - ] - }, - "jsx-evaluated-code": { - "name": "meta.embedded.expression.js", - "begin": "\\{", - "end": "\\}", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.js" - } - }, - "patterns": [ - { - "include": "#expression" - } - ] - }, - "jsx-tag-attributes-illegal": { - "name": "invalid.illegal.attribute.js", - "match": "\\S+" - }, - "jsx-tag-without-attributes": { - "name": "meta.tag.without-attributes.js", - "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", - "end": "()", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "endCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "contentName": "meta.jsx.children.tsx", - "patterns": [ - { - "include": "#jsx-children" - } - ] - }, - "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-child-tag": { - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-tag": { - "name": "meta.tag.js", - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(?=(/>)|(?:()))", - "patterns": [ - { - "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - } - }, - "end": "(?=[/]?>)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#jsx-tag-attributes" - }, - { - "include": "#jsx-tag-attributes-illegal" - } - ] - }, - { - "begin": "(>)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.end.js" - } - }, - "end": "(?=" - }, - "jsx-children": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-child-tag" - }, - { - "include": "#jsx-tag-invalid" - }, - { - "include": "#jsx-evaluated-code" - }, - { - "include": "#jsx-entities" - } - ] - }, - "jsx": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-tag-in-expression" - }, - { - "include": "#jsx-tag-invalid" - } - ] - } - }, - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" + "name.$comment": "** Changed **", + "name": "Mongo Scrapbooks (JavaScript)", + "scopeName.$comment": "** Changed **", + "scopeName": "source.mongo.js", + "fileTypes.$comment": "** Changed from .js/.jsx **", + "fileTypes": [".mongo"], + "uuid.$comment": "** Changed **", + "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", + "patterns": [ + { + "include": "#directives" + }, + { + "include": "#statements" + }, + { + "name": "comment.line.shebang.ts", + "match": "\\A(#!).*(?=$)", + "captures": { + "1": { + "name": "punctuation.definition.comment.ts" + } + } + } + ], + "repository": { + "statements": { + "patterns": [ + { + "include": "#string" + }, + { + "include": "#template" + }, + { + "include": "#comment" + }, + { + "include": "#declaration" + }, + { + "include": "#switch-statement" + }, + { + "include": "#for-loop" + }, + { + "include": "#after-operator-block" + }, + { + "include": "#decl-block" + }, + { + "include": "#control-statement" + }, + { + "include": "#expression" + }, + { + "include": "#punctuation-semicolon" + } + ] + }, + "var-expr": { + "name": "meta.var.expr.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js entity.name.function.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + }, + { + "name": "meta.var-single-variable.expr.js", + "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js variable.other.constant.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + }, + { + "name": "meta.var-single-variable.expr.js", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js variable.other.readwrite.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + } + ] + }, + "var-single-variable-type-annotation": { + "patterns": [ + { + "include": "#type-annotation" + }, + { + "include": "#string" + }, + { + "include": "#comment" + } + ] + }, + "destructuring-variable": { + "patterns": [ + { + "name": "meta.object-binding-pattern-variable.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" + }, + { + "name": "meta.definition.property.js variable.object.property.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.js", + "match": "\\?" + } + ] + } + ] + }, + "method-declaration": { + "name": "meta.method.declaration.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", + "captures": { + "1": { + "name": "storage.modifier.js" + }, + "2": { + "name": "keyword.operator.rest.js" + }, + "3": { + "name": "entity.name.function.js" + }, + "4": { + "name": "keyword.operator.optional.js" + } + } + }, + { + "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type" + } + ] + }, + "type": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#string" + }, + { + "include": "#numeric-literal" + }, + { + "include": "#type-primitive" + }, + { + "include": "#type-builtin-literals" + }, + { + "include": "#type-parameters" + }, + { + "include": "#type-tuple" + }, + { + "include": "#type-object" + }, + { + "include": "#type-operators" + }, + { + "include": "#type-fn-type-parameters" + }, + { + "include": "#type-paren-or-function-parameters" + }, + { + "include": "#type-function-return-type" + }, + { + "include": "#type-name" + } + ] + }, + "function-parameters": { + "name": "meta.parameters.js", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.js" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.js" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#decorator" + }, + { + "include": "#destructuring-parameter" + }, + { + "include": "#parameter-name" + }, + { + "include": "#type-annotation" + }, + { + "include": "#variable-initializer" + }, + { + "name": "punctuation.separator.parameter.js", + "match": "," + } + ] + }, + "type-primitive": { + "name": "support.type.primitive.js", + "match": "(?)\n ))\n )\n )\n)", + "end": "(?<=\\))", + "patterns": [ + { + "include": "#function-parameters" + } + ] + } + ] + }, + "type-operators": { + "patterns": [ + { + "include": "#typeof-operator" + }, + { + "name": "keyword.operator.type.js", + "match": "[&|]" + }, + { + "name": "keyword.operator.expression.keyof.js", + "match": "(?", + "beginCaptures": { + "0": { + "name": "storage.type.function.arrow.js" + } + }, + "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", + "patterns": [ + { + "include": "#comment" + }, + { + "name": "meta.object.type.js", + "begin": "(?<==>)\\s*(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.block.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.js" + } + }, + "patterns": [ + { + "include": "#type-object-members" + } + ] + }, + { + "include": "#type-predicate-operator" + }, + { + "include": "#type" + } + ] + }, + "type-tuple": { + "name": "meta.type.tuple.js", + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "patterns": [ + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "type-name": { + "patterns": [ + { + "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", + "captures": { + "1": { + "name": "entity.name.type.module.js" + }, + "2": { + "name": "punctuation.accessor.js" + } + } + }, + { + "name": "entity.name.type.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + } + ] + }, + "type-parameters": { + "name": "meta.type.parameters.js", + "begin": "(<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.begin.js" + } + }, + "end": "(?=$)|(>)", + "endCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.end.js" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "name": "storage.modifier.js", + "match": "(?)" + }, + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "variable-initializer": { + "patterns": [ + { + "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "support.constant.dom.js" + }, + "3": { + "name": "support.variable.property.dom.js" + } + } + }, + { + "name": "support.class.node.js", + "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", + "patterns": [ + { + "include": "#literal" + }, + { + "include": "#support-objects" + }, + { + "include": "#object-identifiers" + }, + { + "include": "#punctuation-accessor" + }, + { + "name": "entity.name.function.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + }, + { + "include": "#comment" + }, + { + "name": "meta.type.parameters.js", + "begin": "\\<", + "beginCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.begin.js" + } + }, + "end": "\\>", + "endCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.end.js" + } + }, + "patterns": [ + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + { + "include": "#paren-expression" + } + ] + }, + "identifiers": { + "patterns": [ + { + "include": "#object-identifiers" + }, + { + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "entity.name.function.js" + } + } + }, + { + "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.constant.property.js" + } + } + }, + { + "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.property.js" + } + } + }, + { + "name": "variable.other.constant.js", + "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" + }, + { + "name": "variable.other.readwrite.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + } + ] + }, + "object-identifiers": { + "patterns": [ + { + "name": "support.class.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" + }, + { + "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.constant.object.property.js" + }, + "3": { + "name": "variable.other.object.property.js" + } + } + }, + { + "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "variable.other.constant.object.js" + }, + "2": { + "name": "variable.other.object.js" + } + } + } + ] + }, + "cast": { + "patterns": [ + { + "include": "#jsx" + } + ] + }, + "new-expr": { + "name": "new.expr.js", + "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", + "beginCaptures": { + "0": { + "name": "meta.object-literal.key.js" + }, + "1": { + "name": "entity.name.function.js" + }, + "2": { + "name": "punctuation.separator.key-value.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", + "beginCaptures": { + "0": { + "name": "meta.object-literal.key.js" + }, + "1": { + "name": "punctuation.separator.key-value.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "begin": "\\.\\.\\.", + "beginCaptures": { + "0": { + "name": "keyword.operator.spread.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", + "captures": { + "1": { + "name": "variable.other.readwrite.js" + } + } + }, + { + "include": "#punctuation-comma" + } + ] + }, + "expression-operators": { + "patterns": [ + { + "name": "keyword.control.flow.js", + "match": "(?>=|>>>=|\\|=" + }, + { + "name": "keyword.operator.bitwise.shift.js", + "match": "<<|>>>|>>" + }, + { + "name": "keyword.operator.comparison.js", + "match": "===|!==|==|!=" + }, + { + "name": "keyword.operator.relational.js", + "match": "<=|>=|<>|<|>" + }, + { + "name": "keyword.operator.logical.js", + "match": "\\!|&&|\\|\\|" + }, + { + "name": "keyword.operator.bitwise.js", + "match": "\\&|~|\\^|\\|" + }, + { + "name": "keyword.operator.assignment.js", + "match": "\\=" + }, + { + "name": "keyword.operator.decrement.js", + "match": "--" + }, + { + "name": "keyword.operator.increment.js", + "match": "\\+\\+" + }, + { + "name": "keyword.operator.arithmetic.js", + "match": "%|\\*|/|-|\\+" + }, + { + "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", + "captures": { + "1": { + "name": "keyword.operator.arithmetic.js" + } + } + } + ] + }, + "typeof-operator": { + "name": "keyword.operator.expression.typeof.js", + "match": "(?)", + "captures": { + "1": { + "name": "storage.modifier.async.js" + }, + "2": { + "name": "variable.parameter.js" + } + } + }, + { + "name": "meta.arrow.js", + "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", + "beginCaptures": { + "1": { + "name": "storage.modifier.async.js" + } + }, + "end": "(?==>|\\{)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type-parameters" + }, + { + "include": "#function-parameters" + }, + { + "include": "#arrow-return-type" + } + ] + }, + { + "name": "meta.arrow.js", + "begin": "=>", + "beginCaptures": { + "0": { + "name": "storage.type.function.arrow.js" + } + }, + "end": "(?<=\\})|((?!\\{)(?=\\S))", + "patterns": [ + { + "include": "#decl-block" + }, + { + "include": "#expression" + } + ] + } + ] + }, + "arrow-return-type": { + "name": "meta.return.type.arrow.js", + "begin": "(?<=\\))\\s*(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.js" + } + }, + "end": "(?==>|\\{)", + "patterns": [ + { + "name": "meta.object.type.js", + "begin": "(?<=:)\\s*(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.block.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.js" + } + }, + "patterns": [ + { + "include": "#type-object-members" + } + ] + }, + { + "include": "#type-predicate-operator" + }, + { + "include": "#type" + } + ] + }, + "punctuation-comma": { + "name": "punctuation.separator.comma.js", + "match": "," + }, + "punctuation-semicolon": { + "name": "punctuation.terminator.statement.js", + "match": ";" + }, + "punctuation-accessor": { + "name": "punctuation.accessor.js", + "match": "\\." + }, + "paren-expression": { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "meta.brace.round.js" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "meta.brace.round.js" + } + }, + "patterns": [ + { + "include": "#expression" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "qstring-double": { + "name": "string.quoted.double.js", + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(\")|((?:[^\\\\\\n])$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "invalid.illegal.newline.js" + } + }, + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "qstring-single": { + "name": "string.quoted.single.js", + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(\\')|((?:[^\\\\\\n])$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "invalid.illegal.newline.js" + } + }, + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "regex": { + "patterns": [ + { + "name": "string.regexp.js", + "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(/)([gimuy]*)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "keyword.other.js" + } + }, + "patterns": [ + { + "include": "#regexp" + } + ] + }, + { + "name": "string.regexp.js", + "begin": "(?\\s*$)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.js" + } + }, + "end": "(?=$)", + "patterns": [ + { + "name": "meta.tag.js", + "begin": "(<)(reference|amd-dependency|amd-module)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.directive.js" + }, + "2": { + "name": "entity.name.tag.directive.js" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.directive.js" + } + }, + "patterns": [ + { + "name": "entity.other.attribute-name.directive.js", + "match": "path|types|no-default-lib|name" + }, + { + "name": "keyword.operator.assignment.js", + "match": "=" + }, + { + "include": "#string" + } + ] + } + ] + }, + "docblock": { + "patterns": [ + { + "name": "storage.type.class.jsdoc", + "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", + "captures": { + "0": { + "name": "other.meta.jsdoc" + }, + "1": { + "name": "entity.name.type.instance.jsdoc" + }, + "2": { + "name": "variable.other.jsdoc" + }, + "3": { + "name": "other.description.jsdoc" + } + } + }, + { + "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", + "captures": { + "0": { + "name": "other.meta.jsdoc" + }, + "1": { + "name": "entity.name.type.instance.jsdoc" + }, + "2": { + "name": "other.description.jsdoc" + } + } + } + ] + }, + "jsx-tag-attributes": { + "patterns": [ + { + "include": "#jsx-tag-attribute-name" + }, + { + "include": "#jsx-tag-attribute-assignment" + }, + { + "include": "#jsx-string-double-quoted" + }, + { + "include": "#jsx-string-single-quoted" + }, + { + "include": "#jsx-evaluated-code" + } + ] + }, + "jsx-tag-attribute-name": { + "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", + "captures": { + "1": { + "name": "entity.other.attribute-name.js" + } + } + }, + "jsx-tag-attribute-assignment": { + "name": "keyword.operator.assignment.js", + "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" + }, + "jsx-string-double-quoted": { + "name": "string.quoted.double.js", + "begin": "\"", + "end": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-string-single-quoted": { + "name": "string.quoted.single.js", + "begin": "'", + "end": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-entities": { + "patterns": [ + { + "name": "constant.character.entity.js", + "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", + "captures": { + "1": { + "name": "punctuation.definition.entity.js" + }, + "3": { + "name": "punctuation.definition.entity.js" + } + } + }, + { + "name": "invalid.illegal.bad-ampersand.js", + "match": "&" + } + ] + }, + "jsx-evaluated-code": { + "name": "meta.embedded.expression.js", + "begin": "\\{", + "end": "\\}", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.js" + } + }, + "patterns": [ + { + "include": "#expression" + } + ] + }, + "jsx-tag-attributes-illegal": { + "name": "invalid.illegal.attribute.js", + "match": "\\S+" + }, + "jsx-tag-without-attributes": { + "name": "meta.tag.without-attributes.js", + "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", + "end": "()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "contentName": "meta.jsx.children.tsx", + "patterns": [ + { + "include": "#jsx-children" + } + ] + }, + "jsx-tag-in-expression": { + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(/>)|(?:())", + "endCaptures": { + "0": { + "name": "meta.tag.js" + }, + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "entity.name.tag.js" + }, + "4": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-tag" + } + ] + }, + "jsx-child-tag": { + "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(/>)|(?:())", + "endCaptures": { + "0": { + "name": "meta.tag.js" + }, + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "entity.name.tag.js" + }, + "4": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-tag" + } + ] + }, + "jsx-tag": { + "name": "meta.tag.js", + "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(?=(/>)|(?:()))", + "patterns": [ + { + "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + } + }, + "end": "(?=[/]?>)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#jsx-tag-attributes" + }, + { + "include": "#jsx-tag-attributes-illegal" + } + ] + }, + { + "begin": "(>)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + } + }, + "end": "(?=" + }, + "jsx-children": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-child-tag" + }, + { + "include": "#jsx-tag-invalid" + }, + { + "include": "#jsx-evaluated-code" + }, + { + "include": "#jsx-entities" + } + ] + }, + "jsx": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-tag-in-expression" + }, + { + "include": "#jsx-tag-invalid" + } + ] + } + }, + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" } diff --git a/grammar/Readme.md b/grammar/Readme.md index 7d4d7ce13..27fac0582 100644 --- a/grammar/Readme.md +++ b/grammar/Readme.md @@ -1,10 +1,13 @@ -Note: The file `JavaScript.tmLanguage.json` is derived from [TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). +Note: The file `JavaScript.tmLanguage.json` is derived from +[TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). # To update the grammar after making changes: 1. npm run update-grammar -2. Re-comment imports in mongoParser.ts that are not used and cause compile errors +2. Re-comment imports in mongoParser.ts that are not used and cause compile + errors # Debugging the grammar -See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to generate the debug info before trying to launch. +See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to +generate the debug info before trying to launch. diff --git a/grammar/configuration.json b/grammar/configuration.json index 42f2e2c1b..82ae3324e 100644 --- a/grammar/configuration.json +++ b/grammar/configuration.json @@ -1,55 +1,39 @@ { - "comments": { - "lineComment": "//", - "blockComment": [ - "/*", - "*/" - ] - }, - "brackets": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ] - ], - "autoClosingPairs": [ - { - "open": "{", - "close": "}" - }, - { - "open": "[", - "close": "]" - }, - { - "open": "(", - "close": ")" - }, - { - "open": "'", - "close": "'", - "notIn": [ - "string", - "comment" - ] - }, - { - "open": "\"", - "close": "\"", - "notIn": [ - "string" - ] - }, - { - "open": "/**", - "close": " */", - "notIn": [ - "string" - ] - } - ] + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"] + ], + "autoClosingPairs": [ + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "'", + "close": "'", + "notIn": ["string", "comment"] + }, + { + "open": "\"", + "close": "\"", + "notIn": ["string"] + }, + { + "open": "/**", + "close": " */", + "notIn": ["string"] + } + ] } diff --git a/gulpfile.ts b/gulpfile.ts index 3e69c1ffd..55888b8c4 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -3,29 +3,36 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { gulp_webpack } from '@microsoft/vscode-azext-dev'; -import * as fse from 'fs-extra'; -import * as gulp from 'gulp'; -import * as path from 'path'; +import { gulp_webpack } from "@microsoft/vscode-azext-dev"; +import * as fse from "fs-extra"; +import * as gulp from "gulp"; +import * as path from "path"; declare let exports: { [key: string]: unknown }; async function prepareForWebpack(): Promise { - const mainJsPath: string = path.join(__dirname, 'main.js'); - let contents: string = (await fse.readFile(mainJsPath)).toString(); - contents = contents - .replace('out/src/extension', 'dist/extension.bundle') - .replace(', true /* ignoreBundle */', ''); - await fse.writeFile(mainJsPath, contents); + const mainJsPath: string = path.join(__dirname, "main.js"); + let contents: string = (await fse.readFile(mainJsPath)).toString(); + contents = contents + .replace("out/src/extension", "dist/extension.bundle") + .replace(", true /* ignoreBundle */", ""); + await fse.writeFile(mainJsPath, contents); } async function cleanReadme(): Promise { - const readmePath: string = path.join(__dirname, 'README.md'); - let data: string = (await fse.readFile(readmePath)).toString(); - data = data.replace(/.*?/gis, ''); - await fse.writeFile(readmePath, data); + const readmePath: string = path.join(__dirname, "README.md"); + let data: string = (await fse.readFile(readmePath)).toString(); + data = data.replace( + /.*?/gis, + "" + ); + await fse.writeFile(readmePath, data); } -exports['webpack-dev'] = gulp.series(prepareForWebpack, () => gulp_webpack('development')); -exports['webpack-prod'] = gulp.series(prepareForWebpack, () => gulp_webpack('production')); +exports["webpack-dev"] = gulp.series(prepareForWebpack, () => + gulp_webpack("development") +); +exports["webpack-prod"] = gulp.series(prepareForWebpack, () => + gulp_webpack("production") +); exports.cleanReadme = cleanReadme; diff --git a/main.js b/main.js index 01717236a..3fa51d0fb 100644 --- a/main.js +++ b/main.js @@ -10,20 +10,24 @@ // This is in a separate file so we can properly measure extension.bundle.js load time. let perfStats = { - loadStartTime: Date.now(), - loadEndTime: undefined + loadStartTime: Date.now(), + loadEndTime: undefined, }; Object.defineProperty(exports, "__esModule", { value: true }); -const extension = require('./out/src/extension'); +const extension = require("./out/src/extension"); async function activate(ctx) { - return await extension.activateInternal(ctx, perfStats, true /* ignoreBundle */); + return await extension.activateInternal( + ctx, + perfStats, + true /* ignoreBundle */ + ); } async function deactivate(ctx) { - return await extension.deactivateInternal(ctx, perfStats); + return await extension.deactivateInternal(ctx, perfStats); } // Export as entrypoints for vscode diff --git a/package.json b/package.json index 4b494c176..8664bb378 100644 --- a/package.json +++ b/package.json @@ -1,1114 +1,1114 @@ { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", - "publisher": "ms-azuretools", - "displayName": "Azure Databases", - "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "engines": { - "vscode": "^1.66.0" - }, - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "icon": "resources/databases.png", - "categories": [ - "Azure" - ], - "keywords": [ - "Cosmos DB", - "DocumentDB", - "Graph", - "Gremlin", - "MongoDB", - "PostgreSQL" - ], - "preview": true, - "homepage": "https://github.com/microsoft/vscode-cosmosdb/blob/main/README.md", - "bugs": { - "url": "https://github.com/microsoft/vscode-cosmosdb/issues" - }, - "license": "SEE LICENSE IN LICENSE.md", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-cosmosdb" - }, - "main": "./main", - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], - "contributes": { - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - }, - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } - ], - "commands": [ - { - "category": "Azure Databases", - "command": "azureDatabases.createServer", - "title": "Create Server...", - "icon": "$(add)" - }, - { - "category": "Cosmos DB", - "command": "azureDatabases.detachDatabaseAccount", - "title": "Detach" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.loadMore", - "title": "Load More" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.refresh", - "title": "Refresh", - "icon": "$(refresh)" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.reportIssue", - "title": "Report Issue..." - }, - { - "category": "Azure Databases", - "command": "azureDatabases.update", - "title": "Update to Cloud", - "icon": "$(cloud-upload)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachDatabaseAccount", - "title": "Attach Database Account...", - "icon": "$(plug)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachEmulator", - "title": "Attach Emulator..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.connectMongoDB", - "title": "Connect to Database..." - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBCollection", - "title": "Create Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDatabase", - "title": "Create Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDocument", - "title": "Create Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBStoredProcedure", - "title": "Create Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraph", - "title": "Create Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraphDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoCollection", - "title": "Create Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDocument", - "title": "Create Document" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.deleteAccount", - "title": "Delete Account..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBCollection", - "title": "Delete Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDatabase", - "title": "Delete Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDocument", - "title": "Delete Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraph", - "title": "Delete Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraphDatabase", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoCollection", - "title": "Delete Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDB", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDocument", - "title": "Delete Document..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeAllMongoCommands", - "title": "Execute All MongoDB Commands" - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeMongoCommand", - "title": "Execute MongoDB Command" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.importDocument", - "title": "Import Document into a Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.launchMongoShell", - "title": "Launch Shell" - }, - { - "category": "MongoDB", - "command": "cosmosDB.newMongoScrapbook", - "title": "New Mongo Scrapbook", - "icon": "$(new-file)" - }, - { - "category": "MongoDB", - "command": "cosmosDB.openCollection", - "title": "Open Collection" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openDocument", - "title": "Open Document" - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.openGraphExplorer", - "title": "Open Graph Explorer" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.configureFirewall", - "title": "Configure Firewall" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.connectDatabase", - "title": "Connect to Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createDatabase", - "title": "Create Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createFunctionQuery", - "title": "Create Function Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createStoredProcedureQuery", - "title": "Create Stored Procedure Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteDatabase", - "title": "Delete Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteFunction", - "title": "Delete Function..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteServer", - "title": "Delete Server..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteTable", - "title": "Delete Table..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.enterCredentials", - "title": "Enter Server Credentials" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.executeQuery", - "title": "Execute Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openFunction", - "title": "Open Function" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.showPasswordlessWiki", - "title": "Learn more about authenticating with Azure Active Directory", - "icon": "$(warning)" - } - ], - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } - ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId==postgres" - } - ], - "editor/title": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "azureDatabases.createServer", - "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", - "group": "1@1" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteServer", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@1" - }, - { - "command": "postgreSQL.showPasswordlessWiki", - "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", - "group": "inline" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@1" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@2" - }, - { - "command": "cosmosDB.connectMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "2@1" - }, - { - "command": "cosmosDB.deleteMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@4" - }, - { - "command": "cosmosDB.deleteMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraphDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteTable", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteFunction", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", - "group": "1@2" - }, - { - "command": "cosmosDB.attachDatabaseAccount", - "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "1@1" - }, - { - "command": "cosmosDB.attachEmulator", - "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", - "group": "1@2" - }, - { - "command": "cosmosDB.openCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "2@1" - }, - { - "command": "postgreSQL.copyConnectionString", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "2@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", - "group": "1@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "2@1" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@3" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@1" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createFunctionQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "1@1" - }, - { - "command": "postgreSQL.createStoredProcedureQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "1@1" - } - ], - "explorer/context": [ - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId == json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId == postgres" - } - ], - "commandPalette": [ - { - "command": "azureDatabases.loadMore", - "when": "never" - }, - { - "command": "azureDatabases.refresh", - "when": "never" - }, - { - "command": "azureDatabases.update", - "when": "never" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "editorLangId == 'mongo'" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "editorLangId == 'mongo'" - }, - { - "command": "postgreSQL.executeQuery", - "when": "editorLangId == 'postgres'" - } - ] - }, - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" - } - ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" - } - } - } - }, - "scripts": { - "vscode:prepublish": "npm run webpack-prod", - "build": "tsc", - "cleanReadme": "gulp cleanReadme", - "clean": "git clean -dfx", - "compile": "tsc -watch", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", - "all": "npm i && npm run lint && npm test", - "prepare": "husky install" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "extensionDependencies": [ - "ms-azuretools.vscode-azureresourcegroups" - ] + "name": "vscode-cosmosdb", + "displayName": "Azure Databases", + "version": "0.20.1-alpha", + "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", + "categories": [ + "Azure" + ], + "keywords": [ + "Cosmos DB", + "DocumentDB", + "Graph", + "Gremlin", + "MongoDB", + "PostgreSQL" + ], + "homepage": "https://github.com/microsoft/vscode-cosmosdb/blob/main/README.md", + "bugs": { + "url": "https://github.com/microsoft/vscode-cosmosdb/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode-cosmosdb" + }, + "license": "SEE LICENSE IN LICENSE.md", + "publisher": "ms-azuretools", + "main": "./main", + "scripts": { + "all": "npm i && npm run lint && npm test", + "build": "tsc", + "clean": "git clean -dfx", + "cleanReadme": "gulp cleanReadme", + "compile": "tsc -watch", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "prepare": "husky install", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "vscode:prepublish": "npm run webpack-prod", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats" + }, + "contributes": { + "commands": [ + { + "category": "Azure Databases", + "command": "azureDatabases.createServer", + "title": "Create Server...", + "icon": "$(add)" + }, + { + "category": "Cosmos DB", + "command": "azureDatabases.detachDatabaseAccount", + "title": "Detach" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.loadMore", + "title": "Load More" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.reportIssue", + "title": "Report Issue..." + }, + { + "category": "Azure Databases", + "command": "azureDatabases.update", + "title": "Update to Cloud", + "icon": "$(cloud-upload)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachDatabaseAccount", + "title": "Attach Database Account...", + "icon": "$(plug)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachEmulator", + "title": "Attach Emulator..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.connectMongoDB", + "title": "Connect to Database..." + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBCollection", + "title": "Create Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDatabase", + "title": "Create Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDocument", + "title": "Create Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBStoredProcedure", + "title": "Create Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraph", + "title": "Create Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraphDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoCollection", + "title": "Create Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDocument", + "title": "Create Document" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.deleteAccount", + "title": "Delete Account..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBCollection", + "title": "Delete Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDatabase", + "title": "Delete Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDocument", + "title": "Delete Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraph", + "title": "Delete Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraphDatabase", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoCollection", + "title": "Delete Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDB", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDocument", + "title": "Delete Document..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeAllMongoCommands", + "title": "Execute All MongoDB Commands" + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeMongoCommand", + "title": "Execute MongoDB Command" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.importDocument", + "title": "Import Document into a Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.launchMongoShell", + "title": "Launch Shell" + }, + { + "category": "MongoDB", + "command": "cosmosDB.newMongoScrapbook", + "title": "New Mongo Scrapbook", + "icon": "$(new-file)" + }, + { + "category": "MongoDB", + "command": "cosmosDB.openCollection", + "title": "Open Collection" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openDocument", + "title": "Open Document" + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.openGraphExplorer", + "title": "Open Graph Explorer" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.configureFirewall", + "title": "Configure Firewall" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.connectDatabase", + "title": "Connect to Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createDatabase", + "title": "Create Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createFunctionQuery", + "title": "Create Function Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createStoredProcedureQuery", + "title": "Create Stored Procedure Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteDatabase", + "title": "Delete Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteFunction", + "title": "Delete Function..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteServer", + "title": "Delete Server..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteTable", + "title": "Delete Table..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.enterCredentials", + "title": "Enter Server Credentials" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.executeQuery", + "title": "Execute Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openFunction", + "title": "Open Function" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.showPasswordlessWiki", + "title": "Learn more about authenticating with Azure Active Directory", + "icon": "$(warning)" + } + ], + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null + }, + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] + }, + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 + }, + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" + }, + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" + }, + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + }, + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" + ], + "extensions": [ + ".mongo" + ], + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" + ], + "extensions": [ + ".psql" + ] + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" + } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId==postgres" + } + ], + "editor/title": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "azureDatabases.createServer", + "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", + "group": "1@1" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteServer", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@1" + }, + { + "command": "postgreSQL.showPasswordlessWiki", + "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", + "group": "inline" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@1" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@2" + }, + { + "command": "cosmosDB.connectMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "2@1" + }, + { + "command": "cosmosDB.deleteMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@4" + }, + { + "command": "cosmosDB.deleteMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraphDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteTable", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteFunction", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", + "group": "1@2" + }, + { + "command": "cosmosDB.attachDatabaseAccount", + "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "1@1" + }, + { + "command": "cosmosDB.attachEmulator", + "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", + "group": "1@2" + }, + { + "command": "cosmosDB.openCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "2@1" + }, + { + "command": "postgreSQL.copyConnectionString", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "2@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", + "group": "1@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "2@1" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@3" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@1" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createFunctionQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "1@1" + }, + { + "command": "postgreSQL.createStoredProcedureQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "1@1" + } + ], + "explorer/context": [ + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId == json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId == postgres" + } + ], + "commandPalette": [ + { + "command": "azureDatabases.loadMore", + "when": "never" + }, + { + "command": "azureDatabases.refresh", + "when": "never" + }, + { + "command": "azureDatabases.update", + "when": "never" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "editorLangId == 'mongo'" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "editorLangId == 'mongo'" + }, + { + "command": "postgreSQL.executeQuery", + "when": "editorLangId == 'postgres'" + } + ] + }, + "submenus": [ + { + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" + } + ], + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" + }, + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } + ], + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." + } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] + } + } + }, + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "dependencies": { + "@azure/arm-cosmosdb": "15.0.0", + "@azure/arm-postgresql": "6.0.0", + "@azure/arm-postgresql-flexible": "5.0.0", + "@azure/cosmos": "3.6.3", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.0", + "antlr4ts": "0.4.1-alpha.0", + "bson": "1.1.3", + "fs-extra": "8.0.0", + "mongodb": "3.6.10", + "mongodb-extended-json": "1.10.0", + "open": "8.0.0", + "pg": "8.11.2", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.2", + "underscore": "1.12.1", + "vscode-json-languageservice": "3.0.8", + "vscode-languageclient": "6.1.3", + "vscode-languageserver": "6.1.1", + "vscode-languageserver-textdocument": "1.0.1", + "vscode-nls": "4.0.0", + "vscode-uri": "1.0.1" + }, + "devDependencies": { + "@azure/arm-resources": "4.0.0", + "@microsoft/eslint-config-azuretools": "0.1.0", + "@microsoft/vscode-azext-dev": "0.1.4", + "@types/copy-webpack-plugin": "6.4.0", + "@types/documentdb": "1.10.2", + "@types/fs-extra": "8.1.0", + "@types/gulp": "4.0.6", + "@types/mocha": "7.0.2", + "@types/mongodb": "3.3.2", + "@types/node": "14.0.0", + "@types/pg": "8.10.2", + "@types/vscode": "1.66.0", + "@typescript-eslint/eslint-plugin": "4.31.1", + "@vscode/test-electron": "2.1.5", + "antlr4ts-cli": "0.4.0-alpha.4", + "copy-webpack-plugin": "6.4.0", + "eslint": "7.19.0", + "eslint-plugin-import": "2.22.1", + "glob": "7.1.6", + "gulp": "4.0.0", + "husky": "7.0.2", + "mocha": "10.2.0", + "mocha-junit-reporter": "1.18.0", + "mocha-multi-reporters": "1.1.7", + "ts-node": "7.0.1", + "typescript": "4.4.3", + "vsce": "1.87.0", + "webpack": "5.76.0", + "webpack-cli": "4.6.0", + "webpack-log": "3.0.2" + }, + "extensionDependencies": [ + "ms-azuretools.vscode-azureresourcegroups" + ], + "engines": { + "vscode": "1.66.0" + }, + "icon": "resources/databases.png", + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "preview": true, + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255" } diff --git a/resources/icons/theme-agnostic/CosmosDBAccount.svg b/resources/icons/theme-agnostic/CosmosDBAccount.svg index e6d580065..1159de5ab 100644 --- a/resources/icons/theme-agnostic/CosmosDBAccount.svg +++ b/resources/icons/theme-agnostic/CosmosDBAccount.svg @@ -1,22 +1,35 @@ - - - - - - - - - - - Icon-databases-121 - - - - - - - - - - - + + + + + + + + + + + Icon-databases-121 + + + + + + + + + + + diff --git a/resources/icons/theme-agnostic/PostgresServer.svg b/resources/icons/theme-agnostic/PostgresServer.svg index e247e4e71..11be78e38 100644 --- a/resources/icons/theme-agnostic/PostgresServer.svg +++ b/resources/icons/theme-agnostic/PostgresServer.svg @@ -1 +1,27 @@ -Icon-databases-131 \ No newline at end of file + + + + + + + + + + + + + Icon-databases-131 + + + + + + diff --git a/tsconfig.json b/tsconfig.json index 70851034c..2a36e70e3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,33 +1,23 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6", - "dom" - ], - "sourceMap": true, - "noImplicitThis": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "strictNullChecks": true, - "skipLibCheck": true, - "noUnusedParameters": true, - "rootDir": ".", - "experimentalDecorators": true, - "baseUrl": "./", - "alwaysStrict": true, - "paths": { - "*": [ - "node_modules/@types/*", - "*" - ] - } - }, - "exclude": [ - "node_modules", - ".vscode-test", - "gulpfile.ts" - ] + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": ["es6", "dom"], + "sourceMap": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "strictNullChecks": true, + "skipLibCheck": true, + "noUnusedParameters": true, + "rootDir": ".", + "experimentalDecorators": true, + "baseUrl": "./", + "alwaysStrict": true, + "paths": { + "*": ["node_modules/@types/*", "*"] + } + }, + "exclude": ["node_modules", ".vscode-test", "gulpfile.ts"] } diff --git a/webpack.config.js b/webpack.config.js index 70a3c0468..e4e40a706 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,55 +7,51 @@ // See https://github.com/Microsoft/vscode-azuretools/wiki/webpack for guidance -'use strict'; +"use strict"; -const process = require('process'); -const webpack = require('webpack'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); +const process = require("process"); +const webpack = require("webpack"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); const dev = require("@microsoft/vscode-azext-dev"); let DEBUG_WEBPACK = !!process.env.DEBUG_WEBPACK; let config = dev.getDefaultWebpackConfig({ - projectRoot: __dirname, - verbosity: DEBUG_WEBPACK ? 'debug' : 'normal', - - externalNodeModules: [ - // Modules that we can't easily webpack for some reason. - // These and their dependencies will be copied into node_modules rather than placed in the bundle - // Keep this list small, because all the subdependencies will also be excluded - 'mongodb', - 'pg', - 'pg-structure' - ], - entries: { - // Note: Each entry is a completely separate Node.js application that cannot interact with any - // of the others, and that individually includes all dependencies necessary (i.e. common - // dependencies will have a copy in each entry file, no sharing). - - // Create a separate module bundle for the mongo language server (doesn't share any code with extension.bundle.js) - './mongo-languageServer.bundle': './src/mongo/languageServer.ts' - }, - - externals: { - }, // end of externals - - loaderRules: [ - ], // end of loaderRules - - - plugins: [ - // Replace vscode-languageserver/lib/files.js with a modified version that doesn't have webpack issues - new webpack.NormalModuleReplacementPlugin( - - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/vscode-languageserver-files-stub.js') - ) - ] + projectRoot: __dirname, + verbosity: DEBUG_WEBPACK ? "debug" : "normal", + + externalNodeModules: [ + // Modules that we can't easily webpack for some reason. + // These and their dependencies will be copied into node_modules rather than placed in the bundle + // Keep this list small, because all the subdependencies will also be excluded + "mongodb", + "pg", + "pg-structure", + ], + entries: { + // Note: Each entry is a completely separate Node.js application that cannot interact with any + // of the others, and that individually includes all dependencies necessary (i.e. common + // dependencies will have a copy in each entry file, no sharing). + + // Create a separate module bundle for the mongo language server (doesn't share any code with extension.bundle.js) + "./mongo-languageServer.bundle": "./src/mongo/languageServer.ts", + }, + + externals: {}, // end of externals + + loaderRules: [], // end of loaderRules + + plugins: [ + // Replace vscode-languageserver/lib/files.js with a modified version that doesn't have webpack issues + new webpack.NormalModuleReplacementPlugin( + /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, + require.resolve("./build/vscode-languageserver-files-stub.js") + ), + ], }); if (DEBUG_WEBPACK) { - console.log('Config:', config); + console.log("Config:", config); } module.exports = config; From 926ca8582512d88c77280e5b66b06a0d9dcfa6ac Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Fri, 17 Nov 2023 16:53:04 +0200 Subject: [PATCH 17/33] squash! --- package.json | 92 ++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index 8664bb378..e7f5f3401 100644 --- a/package.json +++ b/package.json @@ -1042,60 +1042,60 @@ "onView:azureWorkspace" ], "dependencies": { - "@azure/arm-cosmosdb": "15.0.0", - "@azure/arm-postgresql": "6.0.0", - "@azure/arm-postgresql-flexible": "5.0.0", - "@azure/cosmos": "3.6.3", + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.0", - "antlr4ts": "0.4.1-alpha.0", - "bson": "1.1.3", - "fs-extra": "8.0.0", - "mongodb": "3.6.10", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.3.0", "mongodb-extended-json": "1.10.0", - "open": "8.0.0", - "pg": "8.11.2", + "open": "9.1.0", + "pg": "8.11.3", "pg-connection-string": "2.6.2", "pg-structure": "7.15.0", - "semver": "7.5.2", - "underscore": "1.12.1", - "vscode-json-languageservice": "3.0.8", - "vscode-languageclient": "6.1.3", - "vscode-languageserver": "6.1.1", - "vscode-languageserver-textdocument": "1.0.1", - "vscode-nls": "4.0.0", - "vscode-uri": "1.0.1" + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" }, "devDependencies": { - "@azure/arm-resources": "4.0.0", - "@microsoft/eslint-config-azuretools": "0.1.0", - "@microsoft/vscode-azext-dev": "0.1.4", - "@types/copy-webpack-plugin": "6.4.0", - "@types/documentdb": "1.10.2", - "@types/fs-extra": "8.1.0", - "@types/gulp": "4.0.6", - "@types/mocha": "7.0.2", - "@types/mongodb": "3.3.2", - "@types/node": "14.0.0", - "@types/pg": "8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "4.31.1", - "@vscode/test-electron": "2.1.5", - "antlr4ts-cli": "0.4.0-alpha.4", - "copy-webpack-plugin": "6.4.0", - "eslint": "7.19.0", - "eslint-plugin-import": "2.22.1", - "glob": "7.1.6", - "gulp": "4.0.0", - "husky": "7.0.2", + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.2", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.12", + "@types/fs-extra": "11.0.4", + "@types/gulp": "4.0.17", + "@types/mocha": "10.0.4", + "@types/mongodb": "4.0.6", + "@types/node": "20.9.1", + "@types/pg": "8.10.9", + "@types/vscode": "1.84.1", + "@typescript-eslint/eslint-plugin": "6.11.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.53.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", "mocha": "10.2.0", - "mocha-junit-reporter": "1.18.0", - "mocha-multi-reporters": "1.1.7", - "ts-node": "7.0.1", - "typescript": "4.4.3", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", "vsce": "1.87.0", - "webpack": "5.76.0", - "webpack-cli": "4.6.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", "webpack-log": "3.0.2" }, "extensionDependencies": [ From c4d3917717f7d277a29c7fca131a574d3d5f5bec Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sat, 18 Nov 2023 20:51:52 +0200 Subject: [PATCH 18/33] squash! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e7f5f3401..865404401 100644 --- a/package.json +++ b/package.json @@ -1083,7 +1083,7 @@ "@vscode/test-electron": "2.3.6", "antlr4ts-cli": "0.5.0-alpha.4", "copy-webpack-plugin": "11.0.0", - "eslint": "8.53.0", + "eslint": "8.54.0", "eslint-plugin-import": "2.29.0", "glob": "10.3.10", "gulp": "4.0.2", From bf4e129cd991780f7ac4e879d8e5008e35aa0d6e Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sat, 18 Nov 2023 23:05:07 +0200 Subject: [PATCH 19/33] squash! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 865404401..a74356379 100644 --- a/package.json +++ b/package.json @@ -1076,7 +1076,7 @@ "@types/gulp": "4.0.17", "@types/mocha": "10.0.4", "@types/mongodb": "4.0.6", - "@types/node": "20.9.1", + "@types/node": "20.9.2", "@types/pg": "8.10.9", "@types/vscode": "1.84.1", "@typescript-eslint/eslint-plugin": "6.11.0", From 59798652aed15e7ccbf05a38380a39703b46c4fe Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Sun, 19 Nov 2023 01:35:11 +0200 Subject: [PATCH 20/33] squash! --- README.md | 145 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 7e1e0a465..f8518c0a5 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,77 @@ - # Azure Databases for VS Code (Preview) -[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) +[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) +[![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) -Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). +Browse and query your Azure databases both locally and in the cloud using +[_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure +to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, +Graph (Gremlin), and SQL (previously known as DocumentDB). ![Azure Databases Extension](resources/readme/overview.png) -> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). +> Sign up today for your free Azure account and receive 12 months of free +> popular services, $200 free credit and 25+ always free services 👉 +> [Start Free](https://azure.microsoft.com/free/open-source). # Prerequisites -- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). +- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and + use of the Mongo shell require installing + [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). # Features ## Azure Databases Explorer -- Create a database server by clicking the `+` button in the title -- View database servers and open directly in the portal -- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries -- Click on a document, stored procedure, or query to open in the editor -- Edit a document and persist changes to the cloud -- Attach a Mongo server by clicking the plug icon in the title +- Create a database server by clicking the `+` button in the title +- View database servers and open directly in the portal +- View/Create/Delete databases, collections, graphs, stored procedures, + documents, and queries +- Click on a document, stored procedure, or query to open in the editor +- Edit a document and persist changes to the cloud +- Attach a Mongo server by clicking the plug icon in the title ![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) ## Mongo Scrapbooks + ### Run Mongo Commands with Rich Intellisense -- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string -- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) -- Click on "New Mongo Scrapbook" in the tree title bar -- Click on "Connect to a database" to indicate which database to run the commands against -- Enter your commands and/or comments, eg: `db..find()` -- IntelliSense (auto-completions) will be provided -- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor -- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` -- Save and re-use later -![Mongo Scrapbook](resources/readme/Scrapbook.gif) +- View your MongoDB database account by by clicking "Sign in to Azure..." in + the Azure Resources explorer or using "Attach Database Account" to connect + via a connection string +- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` + if your mongo executable is not already on your system's PATH (many of the + common commands have built-in support and do not require the Mongo shell to + be installed - see [Prerequisites](#prerequisites)) +- Click on "New Mongo Scrapbook" in the tree title bar +- Click on "Connect to a database" to indicate which database to run the + commands against +- Enter your commands and/or comments, eg: `db..find()` +- IntelliSense (auto-completions) will be provided +- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or + `CTRL+"` (Windows and Linux) to execute the line with the cursor +- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` +- Save and re-use later ![Mongo Scrapbook](resources/readme/Scrapbook.gif) ## Import into Cosmos DB -- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! -![Import documents](resources/readme/import_documents.gif) +- You can now import documents from your workspace into CosmosDB. Use the + context menu of a collection or a document file (json) to get started! + ![Import documents](resources/readme/import_documents.gif) ## Create an Azure Databases Server -1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer - > If you don't already have an Azure Account, click "Create a Free Azure Account" +1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure + Resources explorer + > If you don't already have an Azure Account, click "Create a Free Azure + > Account" 1. Select the 'plus' button to open the "Create Resource" menu ![Create resource](resources/readme/createResource.png) @@ -63,42 +82,82 @@ Browse and query your Azure databases both locally and in the cloud using [_scra ## Attach to the Cosmos DB Emulator -* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine -* Right click 'Attached Database Accounts' and select 'Attach Emulator' +- Install and run the + [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) + on your local machine +- Right click 'Attached Database Accounts' and select 'Attach Emulator' ![Attach Emulator](resources/readme/attachEmulator.png) ## Known Issues -- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. -- Graphs are not currently supported with the emulator -- Viewing/editing tables is not currently supported -- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). +- Azure no longer supports gremlin queries on pre-GA graph accounts. If you + see the error "Could not find a valid gremlin endpoint for _graph_", then + choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in + the Overview tab. If it does not take the form of + '...[graph-name].**_gremlin_**.cosmosdb.azure.com...', then you will need to + create a new graph account using the Azure portal or the current version of + the extension. +- Graphs are not currently supported with the emulator +- Viewing/editing tables is not currently supported +- Support for escapes in the scrapbooks is preliminary. We currently do not + support escaped characters as is inside a string - the characters need to be + double escaped. For example, newlines in the string should be '\\\\n' + instead of '\\n' to be recognized correctly. If you find any issues with how + the scrapbook handles escapes, please add to issue + [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). # Contributing -There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): -* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. -* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! -* **Code**: Contribute bug fixes, features or design changes: - * Clone the repository locally and open in VS Code. - * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" - * Open the terminal (press CTRL+ \`) and run `npm install`. - * To build, press F1 and type in `Tasks: Run Build Task`. - * Debug: press F5 to start debugging the extension. +There are several ways you can contribute to our +[repo](https://github.com/Microsoft/vscode-cosmosdb): + +- **Ideas, feature requests and bugs**: We are open to all ideas and we want + to get rid of bugs! Use the + [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to + report a new issue, provide your ideas or contribute to existing threads. +- **Documentation**: Found a typo or strangely worded sentences? Submit a PR! +- **Code**: Contribute bug fixes, features or design changes: + - Clone the repository locally and open in VS Code. + - Run "Extensions: Show Recommended Extensions" from the + [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) + and install all extensions listed under "Workspace Recommendations" + - Open the terminal (press CTRL+ \`) and run + `npm install`. + - To build, press F1 and type in `Tasks: Run Build Task`. + - Debug: press F5 to start debugging the extension. ## Legal -Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. + +Before we can accept your pull request you will need to sign a **Contribution +License Agreement**. All you need to do is to submit a pull request, then the PR +will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, +`cla-signed`, `cla-already-signed`). If you already signed the agreement we will +continue with reviewing the PR, otherwise system will tell you how you can sign +the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. ## Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the +[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any +additional questions or comments. # Telemetry -VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). + +VS Code collects usage data and sends it to Microsoft to help improve our +products and services. Read our +[privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) +to learn more. If you don’t wish to send usage data to Microsoft, you can set +the `telemetry.enableTelemetry` setting to `false`. Learn more in our +[FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). # License + [MIT](LICENSE.md) From 9c13062f02aa58462e4ee5faf4f7072a582f459c Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Mon, 20 Nov 2023 06:58:27 +0200 Subject: [PATCH 21/33] squash! --- .vscode/extensions.json | 8 --- .vscode/launch.json | 145 ---------------------------------------- .vscode/settings.json | 25 ------- .vscode/tasks.json | 23 ------- 4 files changed, 201 deletions(-) delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 41fe51ef5..000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "recommendations": [ - "dbaeumer.vscode-eslint", - "ms-vscode.azure-account", - "ms-azuretools.vscode-azureresourcegroups", - "mike-lischke.vscode-antlr4" - ] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 626d91e57..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,145 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -{ - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}", - "env": { - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "" - } - }, - { - "name": "Launch Extension + Host", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionDevelopmentPath=${workspaceFolder}/../vscode-azureresourcegroups" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}", - "env": { - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "" - } - }, - { - "name": "Launch Extension (webpack)", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], - "preLaunchTask": "npm: webpack", - "env": { - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "", - "DEBUG_WEBPACK": "1" - } - }, - { - "name": "Launch Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/index", - "${workspaceFolder}/test/test.code-workspace" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}", - "env": { - "MOCHA_grep": "", // RegExp of tests to run (empty for all) - "MOCHA_timeout": "0", // Disable time-outs - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "", - "ENABLE_LONG_RUNNING_TESTS": "" - } - }, - { - "name": "Launch Tests (webpack)", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/dist/test/index", - "${workspaceFolder}/test/test.code-workspace" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], - "preLaunchTask": "npm: webpack", - "env": { - "MOCHA_grep": "", // RegExp of tests to run (empty for all) - "MOCHA_timeout": "0", // Disable time-outs - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "", - "DEBUG_WEBPACK": "1", - "ENABLE_LONG_RUNNING_TESTS": "" - } - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Language Server", - "protocol": "inspector", - "port": 6005, - "sourceMaps": true, - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ] - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Extension Host", - "protocol": "inspector", - "port": 5870, - "sourceMaps": true, - "restart": true, - "outFiles": [ - "${workspaceFolder}/out/src" - ] - }, - { - // INSTRUCTIONS - // 1) Point 'input' to a debugging input file and set "input" below to the file's path - // 2) *** IMPORTANT*** Make a whitespace change in mongo.g4 and then save it. This forces debugging info to be generated. - // If this works, you'll see a warning in the Output window. - // 3) Launch this configuration - // 4) See Debug Console output - // 5) In mongo.g4 file, in the editor context menu, you should see options for generating graphs - "name": "Debug Mongo grammar", - "type": "antlr-debug", - "request": "launch", - // This doesn't seem to work: "input": "${workspaceFolder}/${command:AskForTestInput}", - "input": "c:/temp/debugger-input.mongo", - "grammar": "grammar/mongo.g4", - "startRule": "mongoCommands", - "printParseTree": true, - "visualParseTree": true - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 52e1d220a..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, - "source.organizeImports": true - }, - "editor.detectIndentation": false, - "editor.formatOnSave": true, - "editor.insertSpaces": true, - "editor.tabSize": 4, - "files.insertFinalNewline": true, - "files.trimTrailingWhitespace": true, - "search.exclude": { - "out": true, - "**/node_modules": true, - ".vscode-test": true - }, - "typescript.preferences.importModuleSpecifier": "relative", - "typescript.tsdk": "node_modules/typescript/lib", - "antlr4.generation": { - // Settings for "ANTLR4 grammar syntax support" extension - "mode": "internal", - "listeners": true, - "visitors": false - } -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 5c4125cd9..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "compile", - "group": { - "kind": "build", - "isDefault": true - }, - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "problemMatcher": "$tsc-watch" - }, - { - "type": "npm", - "script": "lint", - "problemMatcher": "$eslint-stylish" - } - ] -} From dc157653befaa7958d0b3c66ac0061fb62401678 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Mon, 20 Nov 2023 17:56:24 +0200 Subject: [PATCH 22/33] squash! --- .../IPostgresFunctionQueryWizardContext.ts | 5 +- .../function/createPostgresFunctionQuery.ts | 22 +- .../function/steps/FunctionQueryCreateStep.ts | 24 +- .../FunctionQueryCustomReturnTypeStep.ts | 19 +- .../function/steps/FunctionQueryNameStep.ts | 25 +- .../steps/FunctionQueryReturnTypeStep.ts | 87 ++-- .../createPostgresStoredProcedureQuery.ts | 17 +- .../steps/StoredProcedureQueryCreateStep.ts | 20 +- .../steps/StoredProcedureQueryNameStep.ts | 23 +- .../steps/PostgresServerConfirmPWStep.ts | 40 +- .../steps/PostgresServerCreateStep.ts | 205 ++++---- .../steps/PostgresServerCredPWStep.ts | 99 ++-- .../steps/PostgresServerCredUserStep.ts | 100 ++-- .../steps/PostgresServerNameStep.ts | 143 ++++-- .../steps/PostgresServerSetCredentialsStep.ts | 84 ++-- .../steps/PostgresServerSkuStep.ts | 465 +++++++++--------- 16 files changed, 809 insertions(+), 569 deletions(-) diff --git a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts index 27b32993c..8b4dd5f93 100644 --- a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts @@ -5,6 +5,7 @@ import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; -export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { - returnType?: string; +export interface IPostgresFunctionQueryWizardContext + extends IPostgresQueryWizardContext { + returnType?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts index 8c4df098b..ca281d4d4 100644 --- a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts @@ -11,13 +11,19 @@ import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; -export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], - executeSteps: [new FunctionQueryCreateStep()], - title: 'Create PostgreSQL Function Query' - }); +export async function createPostgresFunctionQuery( + context: IActionContext, + treeItem?: PostgresFunctionsTreeItem +): Promise { + const wizardContext: IPostgresFunctionQueryWizardContext = context; + const wizard = new AzureWizard(wizardContext, { + promptSteps: [ + new FunctionQueryNameStep(), + new FunctionQueryReturnTypeStep(), + ], + executeSteps: [new FunctionQueryCreateStep()], + title: "Create PostgreSQL Function Query", + }); - await runPostgresQueryWizard(wizard, wizardContext, treeItem); + await runPostgresQueryWizard(wizard, wizardContext, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts index 9356882d9..9c0bd1e34 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts @@ -9,18 +9,26 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresFunctionQueryWizardContext): Promise { - context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); - } + public async execute( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.query = defaultFunctionQuery( + nonNullProp(context, "name"), + nonNullProp(context, "returnType") + ); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) +const defaultFunctionQuery = ( + name: string, + returnType: string +) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) RETURNS ${returnType} LANGUAGE plpgsql AS $function$ diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts index cfacc0f64..a37c18995 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts @@ -8,11 +8,18 @@ import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); - } + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.returnType = await context.ui.showInputBox({ + prompt: localize( + "provideCustomReturnType", + "Provide custom return type" + ), + }); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts index 36d798074..78459f842 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts @@ -9,14 +9,21 @@ import { validateIdentifier } from "../../validateIdentifier"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideFunctionName', 'Provide function name'), - validateInput: validateIdentifier - })).trim(); - } + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.name = ( + await context.ui.showInputBox({ + prompt: localize( + "provideFunctionName", + "Provide function name" + ), + validateInput: validateIdentifier, + }) + ).trim(); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts index 63f703793..b69c94a2c 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts @@ -3,48 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, + IWizardOptions, +} from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); - returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + const returnTypeQuickPicks: IAzureQuickPickItem[] = + returnTypes.map((r) => { + return { label: r, data: r }; + }); + returnTypeQuickPicks.push({ + label: localize( + "enterCustomReturnType", + "$(pencil) Enter custom return type..." + ), + data: undefined, + }); - context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize('selectReturnType', 'Select return type') - })).data; - } + context.returnType = ( + await context.ui.showQuickPick(returnTypeQuickPicks, { + placeHolder: localize("selectReturnType", "Select return type"), + }) + ).data; + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } - public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { - return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } + public async getSubWizard( + context: IPostgresFunctionQueryWizardContext + ): Promise< + IWizardOptions | undefined + > { + return context.returnType + ? undefined + : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; + } } // A subset of return types available on pgAdmin const returnTypes: string[] = [ - 'bigint', - 'bigint[]', - 'boolean', - 'boolean[]', - 'character', - 'character[]', - 'date', - 'date[]', - 'integer', - 'integer[]', - 'json', - 'json[]', - 'oid', - 'oid[]', - 'smallint', - 'smallint[]', - 'text', - 'void' + "bigint", + "bigint[]", + "boolean", + "boolean[]", + "character", + "character[]", + "date", + "date[]", + "integer", + "integer[]", + "json", + "json[]", + "oid", + "oid[]", + "smallint", + "smallint[]", + "text", + "void", ]; diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts index f1ddbe51b..b63bf39ae 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts @@ -9,12 +9,15 @@ import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; -export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: 'Create PostgreSQL Stored Procedure Query' - }); +export async function createPostgresStoredProcedureQuery( + context: IActionContext, + treeItem?: PostgresStoredProceduresTreeItem +): Promise { + const wizard = new AzureWizard(context, { + promptSteps: [new StoredProcedureQueryNameStep()], + executeSteps: [new StoredProcedureQueryCreateStep()], + title: "Create PostgreSQL Stored Procedure Query", + }); - await runPostgresQueryWizard(wizard, context, treeItem); + await runPostgresQueryWizard(wizard, context, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts index 2cf3ef916..67bbbbf0c 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts @@ -9,18 +9,22 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); - } + public async execute(context: IPostgresQueryWizardContext): Promise { + context.query = defaultStoredProcedureQuery( + nonNullProp(context, "name") + ); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) +const defaultStoredProcedureQuery = ( + name: string +) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) LANGUAGE plpgsql AS $$ BEGIN diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts index bf9a00392..5b694f378 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts @@ -9,14 +9,19 @@ import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; import { validateIdentifier } from "../../validateIdentifier"; export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), - validateInput: validateIdentifier - })).trim(); - } + public async prompt(context: IPostgresQueryWizardContext): Promise { + context.name = ( + await context.ui.showInputBox({ + prompt: localize( + "provideStoredProcedureName", + "Provide stored procedure name" + ), + validateInput: validateIdentifier, + }) + ).trim(); + } - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts index 2f07d8203..20d13ffbf 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts @@ -8,24 +8,30 @@ import { localize } from "../../../../utils/localize"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize('confirmPW', 'Confirm your password'); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) - }); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const prompt: string = localize("confirmPW", "Confirm your password"); + await context.ui.showInputBox({ + prompt, + password: true, + validateInput: async ( + value: string | undefined + ): Promise => + await this.validatePassword(context, value), + }); + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !!context.adminPassword; + } - private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { - if (passphrase !== context.adminPassword) { - return localize('pwMatch', 'The passwords must match.'); - } + private async validatePassword( + context: IPostgresServerWizardContext, + passphrase: string | undefined + ): Promise { + if (passphrase !== context.adminPassword) { + return localize("pwMatch", "The passwords must match."); + } - return undefined; - } + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts index f73ce810d..549f1e67f 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts @@ -5,100 +5,133 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; +import { + AzureWizardExecuteStep, + callWithMaskHandling, +} from "@microsoft/vscode-azext-utils"; import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { Progress } from "vscode"; +import { ext } from "../../../../extensionVariables"; +import { + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../../../../utils/azureClients"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + AbstractServerCreate, + PostgresServerType, +} from "../../../abstract/models"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; + public priority: number = 150; - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + public async execute( + context: IPostgresServerWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + const locationName: string = ( + await LocationListStep.getLocation(context) + ).name; + const rgName: string = nonNullProp( + nonNullProp(context, "resourceGroup"), + "name" + ); + const size: string = nonNullProp(nonNullProp(context, "sku"), "size"); + const newServerName = nonNullProp(context, "newServerName"); + const password: string = nonNullProp(context, "adminPassword"); - const locationName: string = (await LocationListStep.getLocation(context)).name; - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); - const newServerName = nonNullProp(context, 'newServerName'); - const password: string = nonNullProp(context, 'adminPassword'); + return await callWithMaskHandling(async () => { + const serverType = nonNullProp(context, "serverType"); + const createMessage: string = localize( + "creatingPostgresServer", + 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', + context.newServerName + ); - return await callWithMaskHandling( - async () => { - const serverType = nonNullProp(context, 'serverType'); - const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); + ext.outputChannel.appendLog(createMessage); + progress.report({ message: createMessage }); + const options: AbstractServerCreate = { + location: locationName, + sku: nonNullProp(context, "sku"), + administratorLogin: nonNullProp(context, "shortUserName"), + administratorLoginPassword: password, + size: parseInt(size), + }; - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, 'sku'), - administratorLogin: nonNullProp(context, 'shortUserName'), - administratorLoginPassword: password, - size: parseInt(size) - }; + switch (serverType) { + case PostgresServerType.Single: + const singleClient: SingleModels.PostgreSQLManagementClient = + await createPostgreSQLClient(context); + context.server = + await singleClient.servers.beginCreateAndWait( + rgName, + newServerName, + this.asSingleParameters(options) + ); + break; + case PostgresServerType.Flexible: + const flexiClient: FlexibleModels.PostgreSQLManagementClient = + await createPostgreSQLFlexibleClient(context); + context.server = + await flexiClient.servers.beginCreateAndWait( + rgName, + newServerName, + this.asFlexibleParameters(options) + ); + break; + } + context.server.serverType = serverType; + context.activityResult = context.server as AppResource; + }, password); + } - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); - context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); - context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, - password); - } + public shouldExecute(context: IPostgresServerWizardContext): boolean { + return !context.server; + } - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } - - - private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier - }, - } - } - - private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size - } - } - } - } + private asFlexibleParameters( + parameters: AbstractServerCreate + ): FlexibleModels.Server { + return { + location: parameters.location, + version: "12", + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + storage: { + storageSizeGB: parameters.size, + }, + sku: { + name: parameters.sku.name, + tier: parameters.sku.tier, + }, + }; + } + private asSingleParameters( + parameters: AbstractServerCreate + ): SingleModels.ServerForCreate { + return { + location: parameters.location, + sku: { + name: parameters.sku.name, + capacity: parameters.sku.capacity, + size: parameters.sku.size, + family: parameters.sku.family, + tier: parameters.sku.tier as SingleModels.SkuTier, + }, + properties: { + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: + parameters.administratorLoginPassword, + sslEnforcement: "Enabled", + createMode: "Default", + version: "11", + storageProfile: { + storageMB: parameters.size, + }, + }, + }; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts index c48d40c37..dd5c84c25 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts @@ -3,51 +3,66 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; -const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); +const pwConditionMsg = localize( + "passwordConditionMsg", + "Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.)." +); export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, 'shortUserName'); - context.adminPassword = (await context.ui.showInputBox({ - placeHolder: localize('pwPlaceholder', 'Administrator Password'), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => validatePassword(user, password), - })); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const user = nonNullProp(context, "shortUserName"); + context.adminPassword = await context.ui.showInputBox({ + placeHolder: localize("pwPlaceholder", "Administrator Password"), + prompt: pwConditionMsg, + password: true, + validateInput: (password: string) => + validatePassword(user, password), + }); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.adminPassword; + } } -async function validatePassword(username: string, password: string): Promise { - password = password ? password : ''; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map(substring => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); - } else { - return undefined; - } +async function validatePassword( + username: string, + password: string +): Promise { + password = password ? password : ""; + + const min = 8; + const max = 128; + + const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; + let numOccurrence = 0; + + regex.map((substring) => { + if (password.match(substring)) { + numOccurrence++; + } + }); + + if (password.length < min || password.length > max) { + return localize( + "pwLengthCheck", + "Password must be between {0} and {1} characters.", + min, + max + ); + } else if (numOccurrence < 3) { + return pwConditionMsg; + } else if (password.includes(username)) { + return localize( + "pwUserSimalarityCheck", + "Password cannot contain the username." + ); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts index 7b4890d07..14b7de8f7 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts @@ -3,46 +3,80 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = (await context.ui.showInputBox({ - placeHolder: localize('usernamePlaceholder', 'Administrator Username'), - validateInput: validateUser, - })).trim(); - const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; - context.longUserName = context.shortUserName + usernameSuffix; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + context.shortUserName = ( + await context.ui.showInputBox({ + placeHolder: localize( + "usernamePlaceholder", + "Administrator Username" + ), + validateInput: validateUser, + }) + ).trim(); + const usernameSuffix: string = `@${nonNullProp( + context, + "newServerName" + )}`; + context.longUserName = context.shortUserName + usernameSuffix; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.shortUserName; + } } async function validateUser(username: string): Promise { - username = username ? username.trim() : ''; + username = username ? username.trim() : ""; - const min = 1; - const max = 63; + const min = 1; + const max = 63; - const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; + const restricted = [ + "azure_superuser", + "azure_pg_admin", + "admin", + "administrator", + "root", + "guest", + "public", + ]; - if (username.length < min || username.length > max) { - return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); - } else if (username.match(/^[0-9]+/)) { - return localize('usernameBeginningMatch', 'The name cannot start with a number.'); - } else if (username.toLowerCase().startsWith('pg_')) { - return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map(d => `"${d}"`).join(', '); - return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); - } else { - return undefined; - } + if (username.length < min || username.length > max) { + return localize( + "usernameLenghtMatch", + "The name must be between {0} and {1} characters.", + min, + max + ); + } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { + return localize( + "usernameCharacterCheck", + 'The name can only contain letters, numbers, and the "_" character.' + ); + } else if (username.match(/^[0-9]+/)) { + return localize( + "usernameBeginningMatch", + "The name cannot start with a number." + ); + } else if (username.toLowerCase().startsWith("pg_")) { + return localize( + "usernameStartWithCheck", + 'Admin username cannot start with "pg_".' + ); + } else if (restricted.includes(username.toLowerCase())) { + const restrictedString = restricted.map((d) => `"${d}"`).join(", "); + return localize( + "usernameRestrictedCheck", + "Admin username cannot be any of the following: {0}.", + restrictedString + ); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts index 1af03f5c7..76b25373e 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts @@ -3,58 +3,111 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; -import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { + ResourceGroupListStep, + resourceGroupNamingRules, +} from "@microsoft/vscode-azext-azureutils"; +import { AzureNameStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../../../abstract/AbstractPostgresClient"; +import { + AbstractNameAvailability, + PostgresServerType, +} from "../../../abstract/models"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerNameStep extends AzureNameStep { + public async prompt(context: IPostgresServerWizardContext): Promise { + const client = await createAbstractPostgresClient( + nonNullProp(context, "serverType"), + context + ); + context.newServerName = ( + await context.ui.showInputBox({ + placeHolder: localize("serverNamePlaceholder", "Server name"), + prompt: localize( + "enterServerNamePrompt", + "Provide a name for the PostgreSQL Server." + ), + validateInput: (name: string) => + validatePostgresServerName( + name, + client, + nonNullProp(context, "serverType") + ), + }) + ).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName( + context, + context.newServerName, + resourceGroupNamingRules + ); + } - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: localize('serverNamePlaceholder', 'Server name'), - prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), - validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.newServerName; + } -async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { - name = name ? name.trim() : ''; + protected async isRelatedNameAvailable( + context: IPostgresServerWizardContext, + name: string + ): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } +} - const min = 3; - const max = 63; +async function validatePostgresServerName( + name: string, + client: AbstractPostgresClient, + serverType: PostgresServerType +): Promise { + name = name ? name.trim() : ""; - if (name.length < min || name.length > max) { - return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } else if (!(/^[a-z0-9-]+$/).test(name)) { - return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); - } else if (name.startsWith('-') || name.endsWith('-')) { - return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); - } - const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); + const min = 3; + const max = 63; - if (!availability.nameAvailable) { - return availability.message ? - availability.message : - localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); - } + if (name.length < min || name.length > max) { + return localize( + "serverNameLengthCheck", + "The name must be between {0} and {1} characters.", + min, + max + ); + } else if (!/^[a-z0-9-]+$/.test(name)) { + return localize( + "serverNameCharacterCheck", + "Server name must only contain lowercase letters, numbers, and hyphens." + ); + } else if (name.startsWith("-") || name.endsWith("-")) { + return localize( + "serverNamePrefixSuffixCheck", + "Server name must not start or end in a hyphen." + ); + } + const resourceType = + serverType === PostgresServerType.Single + ? "Microsoft.DBforPostgreSQL" + : "Microsoft.DBforPostgreSQL/flexibleServers"; + const availability: AbstractNameAvailability = + await client.checkNameAvailability.execute({ + name: name, + type: resourceType, + }); - return undefined; + if (!availability.nameAvailable) { + return availability.message + ? availability.message + : localize( + "serverNameAvailabilityCheck", + 'Server name "{0}" is not available.', + name + ); + } + return undefined; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts index 3431e8f00..e93027936 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts @@ -3,44 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; -import { setPostgresCredentials } from '../../setPostgresCredentials'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { Progress } from "vscode"; +import { ext } from "../../../../extensionVariables"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + PostgresAbstractServer, + PostgresServerType, +} from "../../../abstract/models"; +import { setPostgresCredentials } from "../../setPostgresCredentials"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; + public priority: number = 200; - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + public async execute( + context: IPostgresServerWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + let user: string; + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexbile Server instance + if ( + context.serverType && + context.serverType === PostgresServerType.Single + ) { + user = nonNullProp(context, "longUserName"); + } else { + user = nonNullProp(context, "shortUserName"); + } + const newServerName: string = nonNullProp(context, "newServerName"); - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if (context.serverType && context.serverType === PostgresServerType.Single) { - user = nonNullProp(context, 'longUserName'); - } else { - user = nonNullProp(context, 'shortUserName'); - } - const newServerName: string = nonNullProp(context, 'newServerName'); + const setupMessage: string = localize( + "setupCredentialsMessage", + 'Setting up Credentials for server "{0}"...', + newServerName + ); + progress.report({ message: setupMessage }); + ext.outputChannel.appendLog(setupMessage); + const password: string = nonNullProp(context, "adminPassword"); + const server: PostgresAbstractServer = nonNullProp(context, "server"); - const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, 'adminPassword'); - const server: PostgresAbstractServer = nonNullProp(context, 'server'); + await setPostgresCredentials(user, password, nonNullProp(server, "id")); + const completedMessage: string = localize( + "addedCredentialsMessage", + 'Successfully setup credentials for server "{0}".', + newServerName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + } - await setPostgresCredentials(user, password, nonNullProp(server, 'id')); - const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } - - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts index 654cd0430..3efe5e223 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts @@ -2,7 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, +} from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../utils/localize"; import { nonNullProp } from "../../../../utils/nonNull"; import { openUrl } from "../../../../utils/openUrl"; @@ -10,241 +13,257 @@ import { AbstractSku, PostgresServerType } from "../../../abstract/models"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; + label: string; + description: string; + sku: AbstractSku; + group?: string; } export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresServerWizardContext - ): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); - pricingTiers.push({ - label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), - onPicked: async () => { - await openUrl('https://aka.ms/AAcxhvm'); - }, data: undefined - }); + public async prompt(context: IPostgresServerWizardContext): Promise { + const placeHolder: string = localize( + "selectPostgresSku", + "Select the Postgres SKU and options." + ); + const pricingTiers: IAzureQuickPickItem[] = + await this.getPicks(nonNullProp(context, "serverType")); + pricingTiers.push({ + label: localize( + "ShowPricingCalculator", + "$(link-external) Show pricing information..." + ), + onPicked: async () => { + await openUrl("https://aka.ms/AAcxhvm"); + }, + data: undefined, + }); - context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; - } + context.sku = ( + await context.ui.showQuickPick(pricingTiers, { + placeHolder, + suppressPersistence: true, + enableGrouping: true, + }) + ).data; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return context.sku === undefined; + } - public async getPicks(serverType: PostgresServerType): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; + public async getPicks( + serverType: PostgresServerType + ): Promise[]> { + const options: IAzureQuickPickItem[] = []; + const skuOptions: ISkuOption[] = + serverType === PostgresServerType.Single + ? singleServerSkus + : flexibleServerSkus; - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: option.group || localize('addlOptions', 'Additional Options') - }); - }); - return options; - } + skuOptions.forEach((option) => { + options.push({ + label: option.label, + description: localize( + nonNullProp(option.sku, "name"), + option.description + ), + data: option.sku, + group: + option.group || + localize("addlOptions", "Additional Options"), + }); + }); + return options; + } } -const recommendedGroup = localize('recommendGroup', 'Recommended'); +const recommendedGroup = localize("recommendGroup", "Recommended"); const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, + { + label: "B1", + description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", + sku: { + name: "B_Gen5_1", + tier: "Basic", + capacity: 1, + family: "Gen5", + size: "5120", + }, + group: recommendedGroup, + }, + { + label: "B2", + description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", + sku: { + name: "B_Gen5_2", + tier: "Basic", + capacity: 2, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP2", + description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_2", + tier: "GeneralPurpose", + capacity: 2, + family: "Gen5", + size: "51200", + }, + group: recommendedGroup, + }, + { + label: "GP4", + description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_4", + tier: "GeneralPurpose", + capacity: 4, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP8", + description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_8", + tier: "GeneralPurpose", + capacity: 8, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP16", + description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_16", + tier: "GeneralPurpose", + capacity: 16, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP32", + description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_32", + tier: "GeneralPurpose", + capacity: 32, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP64", + description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_64", + tier: "GeneralPurpose", + capacity: 64, + family: "Gen5", + size: "204800", + }, + }, ]; // Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 // See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, + { + label: "B1ms", + description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", + sku: { + name: "Standard_B1ms", + tier: "Burstable", + capacity: 1, + size: "32", + }, + group: recommendedGroup, + }, + { + label: "B2s", + description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", + sku: { + name: "Standard_B2s", + tier: "Burstable", + capacity: 2, + size: "32", + }, + }, + { + label: "D2s_v3", + description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", + sku: { + name: "Standard_D2s_v3", + tier: "GeneralPurpose", + capacity: 2, + size: "32", + }, + group: recommendedGroup, + }, + { + label: "D4s_v3", + description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", + sku: { + name: "Standard_D4s_v3", + tier: "GeneralPurpose", + capacity: 4, + size: "32", + }, + }, + { + label: "D8s_v3", + description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", + sku: { + name: "Standard_D8s_v3", + tier: "GeneralPurpose", + capacity: 8, + size: "64", + }, + }, + { + label: "D16s_v3", + description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", + sku: { + name: "Standard_D16s_v3", + tier: "GeneralPurpose", + capacity: 16, + size: "64", + }, + }, + { + label: "D32s_v3", + description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", + sku: { + name: "Standard_D32s_v3", + tier: "GeneralPurpose", + capacity: 32, + size: "64", + }, + }, + { + label: "D48s_v3", + description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", + sku: { + name: "Standard_D48s_v3", + tier: "GeneralPurpose", + capacity: 48, + size: "256", + }, + }, + { + label: "D64s_v3", + description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", + sku: { + name: "Standard_D64s_v3", + tier: "GeneralPurpose", + capacity: 64, + size: "256", + }, + }, ]; From 173f560d30708aea9c60aacf1b100793a92068a9 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Wed, 22 Nov 2023 05:04:30 +0200 Subject: [PATCH 23/33] squash! --- .azure-pipelines/common/build.yml | 16 - .azure-pipelines/common/lint.yml | 10 - .azure-pipelines/common/package.yml | 26 - .azure-pipelines/common/sbom.yml | 13 - .azure-pipelines/common/test.yml | 32 - .../compliance/CredScanSuppressions.json | 45 - .../compliance/PoliCheckExclusions.xml | 10 - .azure-pipelines/compliance/compliance.yml | 36 - .azure-pipelines/linux/xvfb.init | 56 - .azure-pipelines/main.yml | 54 - .husky/pre-commit | 4 - package.json | 2232 +++++++++-------- 12 files changed, 1120 insertions(+), 1414 deletions(-) delete mode 100644 .azure-pipelines/common/build.yml delete mode 100644 .azure-pipelines/common/lint.yml delete mode 100644 .azure-pipelines/common/package.yml delete mode 100644 .azure-pipelines/common/sbom.yml delete mode 100644 .azure-pipelines/common/test.yml delete mode 100644 .azure-pipelines/compliance/CredScanSuppressions.json delete mode 100644 .azure-pipelines/compliance/PoliCheckExclusions.xml delete mode 100644 .azure-pipelines/compliance/compliance.yml delete mode 100644 .azure-pipelines/linux/xvfb.init delete mode 100644 .azure-pipelines/main.yml delete mode 100755 .husky/pre-commit diff --git a/.azure-pipelines/common/build.yml b/.azure-pipelines/common/build.yml deleted file mode 100644 index d287b9eb2..000000000 --- a/.azure-pipelines/common/build.yml +++ /dev/null @@ -1,16 +0,0 @@ -steps: -- task: NodeTool@0 - displayName: 'Use Node 14.x' - inputs: - versionSpec: 14.x - -- task: Npm@1 - displayName: 'npm ci' - inputs: - command: ci - -- task: Npm@1 - displayName: 'Build' - inputs: - command: custom - customCommand: run build diff --git a/.azure-pipelines/common/lint.yml b/.azure-pipelines/common/lint.yml deleted file mode 100644 index 66d82cb8b..000000000 --- a/.azure-pipelines/common/lint.yml +++ /dev/null @@ -1,10 +0,0 @@ -steps: -- task: Npm@1 - displayName: 'Lint' - inputs: - command: custom - customCommand: run lint - -- task: ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - condition: ne(variables['System.PullRequest.IsFork'], 'True') diff --git a/.azure-pipelines/common/package.yml b/.azure-pipelines/common/package.yml deleted file mode 100644 index 13555193e..000000000 --- a/.azure-pipelines/common/package.yml +++ /dev/null @@ -1,26 +0,0 @@ -steps: -- task: Npm@1 - displayName: 'cleanReadme' - inputs: - command: custom - customCommand: run cleanReadme - -- task: Npm@1 - displayName: 'Package' - inputs: - command: custom - customCommand: run package - -- task: CopyFiles@2 - displayName: 'Copy vsix to staging directory' - inputs: - Contents: '**/*.vsix' - TargetFolder: '$(build.artifactstagingdirectory)' - -- task: PublishBuildArtifacts@1 - displayName: 'Publish artifacts: vsix' - inputs: - PathtoPublish: '$(build.artifactstagingdirectory)' - ArtifactName: vsix - # Only publish vsix from linux build since we use this to release and want to stay consistent - condition: and(eq(variables['Agent.OS'], 'Linux'), ne(variables['System.PullRequest.IsFork'], 'True')) diff --git a/.azure-pipelines/common/sbom.yml b/.azure-pipelines/common/sbom.yml deleted file mode 100644 index fa7c4cf28..000000000 --- a/.azure-pipelines/common/sbom.yml +++ /dev/null @@ -1,13 +0,0 @@ -steps: - - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: "SBoM Generation Task" - inputs: - BuildDropPath: "$(Build.ArtifactStagingDirectory)" - condition: ne(variables['System.PullRequest.IsFork'], 'True') - - - task: PublishBuildArtifacts@1 - displayName: "Publish artifacts: sbom" - inputs: - PathtoPublish: "$(Build.ArtifactStagingDirectory)/_manifest" - ArtifactName: _manifest - condition: ne(variables['System.PullRequest.IsFork'], 'True') diff --git a/.azure-pipelines/common/test.yml b/.azure-pipelines/common/test.yml deleted file mode 100644 index 9e4a65629..000000000 --- a/.azure-pipelines/common/test.yml +++ /dev/null @@ -1,32 +0,0 @@ -steps: -- script: | - sudo cp .azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - displayName: 'Start X Virtual Frame Buffer' - condition: eq(variables['Agent.OS'], 'Linux') - -- task: Npm@1 - displayName: 'Test' - inputs: - command: custom - customCommand: test - env: - SERVICE_PRINCIPAL_CLIENT_ID: $(SERVICE_PRINCIPAL_CLIENT_ID) - SERVICE_PRINCIPAL_SECRET: $(SERVICE_PRINCIPAL_SECRET) - SERVICE_PRINCIPAL_DOMAIN: $(SERVICE_PRINCIPAL_DOMAIN) - DISPLAY: :10 # Only necessary for linux test - -- task: Npm@1 - displayName: 'Unit Test' - inputs: - command: custom - customCommand: run unittest - -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '*-results.xml' - testRunTitle: '$(Agent.OS)' - condition: succeededOrFailed() diff --git a/.azure-pipelines/compliance/CredScanSuppressions.json b/.azure-pipelines/compliance/CredScanSuppressions.json deleted file mode 100644 index a3567c7ec..000000000 --- a/.azure-pipelines/compliance/CredScanSuppressions.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "tool": "Credential Scanner", - "suppressions": [ - { - "folder": "node_modules\\", - "_justification": "No need to scan external node modules." - }, - { - "file": "out\\test\\docDBConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "out\\test\\mongoConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "test\\docDBConnectionStrings.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "test\\mongoConnectionStrings.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\test\\docDBConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\test\\mongoConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\extension.bundle.js.map", - "_justification": "Should be covered by scanning the pre-bundled files and it's unclear why the 'map' file in particular is getting flagged." - }, - { - "file": "test\\mongoGetCommand.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\mongo-languageServer.bundle.js.map", - "_justification": "Should be covered by scanning the pre-bundled files and it's unclear why the 'map' file in particular is getting flagged." - } - ] -} diff --git a/.azure-pipelines/compliance/PoliCheckExclusions.xml b/.azure-pipelines/compliance/PoliCheckExclusions.xml deleted file mode 100644 index 8188f1d5f..000000000 --- a/.azure-pipelines/compliance/PoliCheckExclusions.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - NODE_MODULES|DIST - - - - - - - diff --git a/.azure-pipelines/compliance/compliance.yml b/.azure-pipelines/compliance/compliance.yml deleted file mode 100644 index f10805317..000000000 --- a/.azure-pipelines/compliance/compliance.yml +++ /dev/null @@ -1,36 +0,0 @@ -steps: -- task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@1 - displayName: 'Run PoliCheck' - inputs: - targetType: F # search files and folders - optionsUEPATH: '$(Build.SourcesDirectory)/.azure-pipelines/compliance/PoliCheckExclusions.xml' - continueOnError: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@2 - displayName: 'Run CredScan' - inputs: - toolMajorVersion: V2 - suppressionsFile: '$(Build.SourcesDirectory)/.azure-pipelines/compliance/CredScanSuppressions.json' - debugMode: true # Needed to suppress folders - folderSuppression: true - continueOnError: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 - displayName: 'AntiMalware Scanner' - inputs: - FileDirPath: '$(Build.SourcesDirectory)' - EnableServices: true - continueOnError: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 - displayName: 'Publish Security Analysis Logs' - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1 - displayName: 'Post Analysis' - inputs: - AllTools: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') diff --git a/.azure-pipelines/linux/xvfb.init b/.azure-pipelines/linux/xvfb.init deleted file mode 100644 index f2f5e422d..000000000 --- a/.azure-pipelines/linux/xvfb.init +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# -# COPIED FROM https://github.com/microsoft/vscode/blob/01e9903967417ba243cec705445eef9ecbfebfea/build/azure-pipelines/linux/xvfb.init -# -# -# /etc/rc.d/init.d/xvfbd -# -# chkconfig: 345 95 28 -# description: Starts/Stops X Virtual Framebuffer server -# processname: Xvfb -# -### BEGIN INIT INFO -# Provides: xvfb -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Start xvfb at boot time -# Description: Enable xvfb provided by daemon. -### END INIT INFO - -[ "${NETWORKING}" = "no" ] && exit 0 - -PROG="/usr/bin/Xvfb" -PROG_OPTIONS=":10 -ac -screen 0 1024x768x24" -PROG_OUTPUT="/tmp/Xvfb.out" - -case "$1" in - start) - echo "Starting : X Virtual Frame Buffer " - $PROG $PROG_OPTIONS>>$PROG_OUTPUT 2>&1 & - disown -ar - ;; - stop) - echo "Shutting down : X Virtual Frame Buffer" - killproc $PROG - RETVAL=$? - [ $RETVAL -eq 0 ] && /bin/rm -f /var/lock/subsys/Xvfb - /var/run/Xvfb.pid - echo - ;; - restart|reload) - $0 stop - $0 start - RETVAL=$? - ;; - status) - status Xvfb - RETVAL=$? - ;; - *) - echo $"Usage: $0 (start|stop|restart|reload|status)" - exit 1 -esac - -exit $RETVAL diff --git a/.azure-pipelines/main.yml b/.azure-pipelines/main.yml deleted file mode 100644 index 8adaf3c97..000000000 --- a/.azure-pipelines/main.yml +++ /dev/null @@ -1,54 +0,0 @@ -variables: - ${{ if eq(variables['Build.Reason'], 'Schedule') }}: - ENABLE_LONG_RUNNING_TESTS: true - ENABLE_COMPLIANCE: true - -jobs: -- job: Windows - pool: - vmImage: windows-latest - steps: - - template: common/build.yml - - template: common/package.yml - - template: common/lint.yml - - template: compliance/compliance.yml # Only works on Windows - - template: common/test.yml - -- job: Linux - pool: - vmImage: ubuntu-latest - steps: - - template: common/build.yml - - template: common/package.yml - - template: common/sbom.yml # only generate on linux - - template: common/lint.yml - - template: common/test.yml - variables: - Codeql.Enabled: $[in(variables['Build.Reason'], 'Schedule')] # Enable CodeQL only on scheduled builds because it is slow - -- job: macOS - pool: - vmImage: macOS-latest - steps: - - template: common/build.yml - - template: common/package.yml - - template: common/lint.yml - - template: common/test.yml - -trigger: - branches: - include: - - '*' - -pr: - branches: - include: - - '*' - -schedules: -- cron: "30 10 * * *" - displayName: Nightly at 3:30 PT - always: true # Run even when there are no code changes - branches: - include: - - main diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 901b4c3f8..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx vscode-sort-package-json diff --git a/package.json b/package.json index a74356379..c8d29ef2d 100644 --- a/package.json +++ b/package.json @@ -1,1114 +1,1122 @@ { - "name": "vscode-cosmosdb", - "displayName": "Azure Databases", - "version": "0.20.1-alpha", - "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "categories": [ - "Azure" - ], - "keywords": [ - "Cosmos DB", - "DocumentDB", - "Graph", - "Gremlin", - "MongoDB", - "PostgreSQL" - ], - "homepage": "https://github.com/microsoft/vscode-cosmosdb/blob/main/README.md", - "bugs": { - "url": "https://github.com/microsoft/vscode-cosmosdb/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-cosmosdb" - }, - "license": "SEE LICENSE IN LICENSE.md", - "publisher": "ms-azuretools", - "main": "./main", - "scripts": { - "all": "npm i && npm run lint && npm test", - "build": "tsc", - "clean": "git clean -dfx", - "cleanReadme": "gulp cleanReadme", - "compile": "tsc -watch", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "prepare": "husky install", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "vscode:prepublish": "npm run webpack-prod", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats" - }, - "contributes": { - "commands": [ - { - "category": "Azure Databases", - "command": "azureDatabases.createServer", - "title": "Create Server...", - "icon": "$(add)" - }, - { - "category": "Cosmos DB", - "command": "azureDatabases.detachDatabaseAccount", - "title": "Detach" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.loadMore", - "title": "Load More" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.refresh", - "title": "Refresh", - "icon": "$(refresh)" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.reportIssue", - "title": "Report Issue..." - }, - { - "category": "Azure Databases", - "command": "azureDatabases.update", - "title": "Update to Cloud", - "icon": "$(cloud-upload)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachDatabaseAccount", - "title": "Attach Database Account...", - "icon": "$(plug)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachEmulator", - "title": "Attach Emulator..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.connectMongoDB", - "title": "Connect to Database..." - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBCollection", - "title": "Create Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDatabase", - "title": "Create Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDocument", - "title": "Create Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBStoredProcedure", - "title": "Create Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraph", - "title": "Create Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraphDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoCollection", - "title": "Create Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDocument", - "title": "Create Document" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.deleteAccount", - "title": "Delete Account..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBCollection", - "title": "Delete Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDatabase", - "title": "Delete Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDocument", - "title": "Delete Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraph", - "title": "Delete Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraphDatabase", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoCollection", - "title": "Delete Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDB", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDocument", - "title": "Delete Document..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeAllMongoCommands", - "title": "Execute All MongoDB Commands" - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeMongoCommand", - "title": "Execute MongoDB Command" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.importDocument", - "title": "Import Document into a Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.launchMongoShell", - "title": "Launch Shell" - }, - { - "category": "MongoDB", - "command": "cosmosDB.newMongoScrapbook", - "title": "New Mongo Scrapbook", - "icon": "$(new-file)" - }, - { - "category": "MongoDB", - "command": "cosmosDB.openCollection", - "title": "Open Collection" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openDocument", - "title": "Open Document" - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.openGraphExplorer", - "title": "Open Graph Explorer" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.configureFirewall", - "title": "Configure Firewall" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.connectDatabase", - "title": "Connect to Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createDatabase", - "title": "Create Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createFunctionQuery", - "title": "Create Function Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createStoredProcedureQuery", - "title": "Create Stored Procedure Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteDatabase", - "title": "Delete Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteFunction", - "title": "Delete Function..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteServer", - "title": "Delete Server..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteTable", - "title": "Delete Table..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.enterCredentials", - "title": "Enter Server Credentials" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.executeQuery", - "title": "Execute Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openFunction", - "title": "Open Function" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.showPasswordlessWiki", - "title": "Learn more about authenticating with Azure Active Directory", - "icon": "$(warning)" - } - ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" - } - } - }, - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } - ], - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" - } - ], - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId==postgres" - } - ], - "editor/title": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "azureDatabases.createServer", - "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", - "group": "1@1" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteServer", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@1" - }, - { - "command": "postgreSQL.showPasswordlessWiki", - "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", - "group": "inline" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@1" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@2" - }, - { - "command": "cosmosDB.connectMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "2@1" - }, - { - "command": "cosmosDB.deleteMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@4" - }, - { - "command": "cosmosDB.deleteMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraphDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteTable", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteFunction", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", - "group": "1@2" - }, - { - "command": "cosmosDB.attachDatabaseAccount", - "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "1@1" - }, - { - "command": "cosmosDB.attachEmulator", - "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", - "group": "1@2" - }, - { - "command": "cosmosDB.openCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "2@1" - }, - { - "command": "postgreSQL.copyConnectionString", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "2@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", - "group": "1@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "2@1" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@3" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@1" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createFunctionQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "1@1" - }, - { - "command": "postgreSQL.createStoredProcedureQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "1@1" - } - ], - "explorer/context": [ - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId == json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId == postgres" - } - ], - "commandPalette": [ - { - "command": "azureDatabases.loadMore", - "when": "never" - }, - { - "command": "azureDatabases.refresh", - "when": "never" - }, - { - "command": "azureDatabases.update", - "when": "never" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "editorLangId == 'mongo'" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "editorLangId == 'mongo'" - }, - { - "command": "postgreSQL.executeQuery", - "when": "editorLangId == 'postgres'" - } - ] - }, - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } - ], - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - } - }, - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], - "dependencies": { - "@azure/arm-cosmosdb": "15.5.0", - "@azure/arm-postgresql": "6.1.0", - "@azure/arm-postgresql-flexible": "7.1.0", - "@azure/cosmos": "4.0.0", - "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.3", - "antlr4ts": "0.5.0-alpha.4", - "bson": "6.2.0", - "fs-extra": "11.1.1", - "mongodb": "6.3.0", - "mongodb-extended-json": "1.10.0", - "open": "9.1.0", - "pg": "8.11.3", - "pg-connection-string": "2.6.2", - "pg-structure": "7.15.0", - "semver": "7.5.4", - "underscore": "1.13.6", - "vscode-json-languageservice": "5.3.7", - "vscode-languageclient": "9.0.1", - "vscode-languageserver": "9.0.1", - "vscode-languageserver-textdocument": "1.0.11", - "vscode-nls": "5.2.0", - "vscode-uri": "3.0.8" - }, - "devDependencies": { - "@azure/arm-resources": "5.2.0", - "@microsoft/eslint-config-azuretools": "0.2.2", - "@microsoft/vscode-azext-dev": "2.0.2", - "@types/copy-webpack-plugin": "8.0.1", - "@types/documentdb": "1.10.12", - "@types/fs-extra": "11.0.4", - "@types/gulp": "4.0.17", - "@types/mocha": "10.0.4", - "@types/mongodb": "4.0.6", - "@types/node": "20.9.2", - "@types/pg": "8.10.9", - "@types/vscode": "1.84.1", - "@typescript-eslint/eslint-plugin": "6.11.0", - "@vscode/test-electron": "2.3.6", - "antlr4ts-cli": "0.5.0-alpha.4", - "copy-webpack-plugin": "11.0.0", - "eslint": "8.54.0", - "eslint-plugin-import": "2.29.0", - "glob": "10.3.10", - "gulp": "4.0.2", - "husky": "8.0.3", - "mocha": "10.2.0", - "mocha-junit-reporter": "2.2.1", - "mocha-multi-reporters": "1.5.1", - "ts-node": "10.9.1", - "typescript": "5.2.2", - "vsce": "1.87.0", - "webpack": "5.89.0", - "webpack-cli": "5.1.4", - "webpack-log": "3.0.2" - }, - "extensionDependencies": [ - "ms-azuretools.vscode-azureresourcegroups" - ], - "engines": { - "vscode": "1.66.0" - }, - "icon": "resources/databases.png", - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "preview": true, - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255" + "name": "vscode-cosmosdb", + "displayName": "Azure Databases", + "version": "0.0.1", + "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", + "categories": [ + "Azure" + ], + "keywords": [ + "Cosmos DB", + "DocumentDB", + "Graph", + "Gremlin", + "MongoDB", + "PostgreSQL" + ], + "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", + "bugs": { + "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" + }, + "license": "MIT", + "publisher": "playform", + "main": "./main", + "scripts": { + "all": "npm i && npm run lint && npm test", + "build": "tsc", + "clean": "git clean -dfx", + "cleanReadme": "gulp cleanReadme", + "compile": "tsc -watch", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "prepare": "husky install", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "vscode:prepublish": "npm run webpack-prod", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", + "prepublishOnly": "TypeScriptESBuild 'Source/**/*.ts'" + }, + "contributes": { + "commands": [ + { + "category": "Azure Databases", + "command": "azureDatabases.createServer", + "title": "Create Server...", + "icon": "$(add)" + }, + { + "category": "Cosmos DB", + "command": "azureDatabases.detachDatabaseAccount", + "title": "Detach" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.loadMore", + "title": "Load More" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.reportIssue", + "title": "Report Issue..." + }, + { + "category": "Azure Databases", + "command": "azureDatabases.update", + "title": "Update to Cloud", + "icon": "$(cloud-upload)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachDatabaseAccount", + "title": "Attach Database Account...", + "icon": "$(plug)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachEmulator", + "title": "Attach Emulator..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.connectMongoDB", + "title": "Connect to Database..." + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBCollection", + "title": "Create Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDatabase", + "title": "Create Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDocument", + "title": "Create Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBStoredProcedure", + "title": "Create Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraph", + "title": "Create Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraphDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoCollection", + "title": "Create Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDocument", + "title": "Create Document" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.deleteAccount", + "title": "Delete Account..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBCollection", + "title": "Delete Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDatabase", + "title": "Delete Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDocument", + "title": "Delete Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraph", + "title": "Delete Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraphDatabase", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoCollection", + "title": "Delete Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDB", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDocument", + "title": "Delete Document..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeAllMongoCommands", + "title": "Execute All MongoDB Commands" + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeMongoCommand", + "title": "Execute MongoDB Command" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.importDocument", + "title": "Import Document into a Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.launchMongoShell", + "title": "Launch Shell" + }, + { + "category": "MongoDB", + "command": "cosmosDB.newMongoScrapbook", + "title": "New Mongo Scrapbook", + "icon": "$(new-file)" + }, + { + "category": "MongoDB", + "command": "cosmosDB.openCollection", + "title": "Open Collection" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openDocument", + "title": "Open Document" + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.openGraphExplorer", + "title": "Open Graph Explorer" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.configureFirewall", + "title": "Configure Firewall" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.connectDatabase", + "title": "Connect to Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createDatabase", + "title": "Create Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createFunctionQuery", + "title": "Create Function Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createStoredProcedureQuery", + "title": "Create Stored Procedure Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteDatabase", + "title": "Delete Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteFunction", + "title": "Delete Function..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteServer", + "title": "Delete Server..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteTable", + "title": "Delete Table..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.enterCredentials", + "title": "Enter Server Credentials" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.executeQuery", + "title": "Execute Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openFunction", + "title": "Open Function" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.showPasswordlessWiki", + "title": "Learn more about authenticating with Azure Active Directory", + "icon": "$(warning)" + } + ], + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null + }, + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] + }, + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 + }, + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" + }, + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" + }, + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + }, + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" + ], + "extensions": [ + ".mongo" + ], + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" + ], + "extensions": [ + ".psql" + ] + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" + } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId==postgres" + } + ], + "editor/title": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "azureDatabases.createServer", + "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", + "group": "1@1" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteServer", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@1" + }, + { + "command": "postgreSQL.showPasswordlessWiki", + "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", + "group": "inline" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@1" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@2" + }, + { + "command": "cosmosDB.connectMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "2@1" + }, + { + "command": "cosmosDB.deleteMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@4" + }, + { + "command": "cosmosDB.deleteMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraphDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteTable", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteFunction", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", + "group": "1@2" + }, + { + "command": "cosmosDB.attachDatabaseAccount", + "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "1@1" + }, + { + "command": "cosmosDB.attachEmulator", + "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", + "group": "1@2" + }, + { + "command": "cosmosDB.openCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "2@1" + }, + { + "command": "postgreSQL.copyConnectionString", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "2@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", + "group": "1@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "2@1" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@3" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@1" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createFunctionQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "1@1" + }, + { + "command": "postgreSQL.createStoredProcedureQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "1@1" + } + ], + "explorer/context": [ + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId == json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId == postgres" + } + ], + "commandPalette": [ + { + "command": "azureDatabases.loadMore", + "when": "never" + }, + { + "command": "azureDatabases.refresh", + "when": "never" + }, + { + "command": "azureDatabases.update", + "when": "never" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "editorLangId == 'mongo'" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "editorLangId == 'mongo'" + }, + { + "command": "postgreSQL.executeQuery", + "when": "editorLangId == 'postgres'" + } + ] + }, + "submenus": [ + { + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" + } + ], + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" + }, + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } + ], + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." + } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] + } + } + }, + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "dependencies": { + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.3.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" + }, + "devDependencies": { + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.2", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.12", + "@types/fs-extra": "11.0.4", + "@types/gulp": "4.0.17", + "@types/mocha": "10.0.4", + "@types/mongodb": "4.0.6", + "@types/node": "20.9.2", + "@types/pg": "8.10.9", + "@types/vscode": "1.84.1", + "@typescript-eslint/eslint-plugin": "6.11.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.2.2", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2", + "typescript-esbuild": "0.3.1" + }, + "extensionDependencies": [ + "ms-azuretools.vscode-azureresourcegroups" + ], + "icon": "resources/databases.png", + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "preview": true, + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", + "type": "module", + "private": "false", + "publishConfig": { + "access": "public" + }, + "author": { + "name": "Nikola Hristov", + "email": "nikola@nikolahristov.tech", + "url": "https://nikolahristov.tech" + } } From 9c2bb37afcd076f234c6ff51b62db9cf3690a7e2 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Wed, 22 Nov 2023 05:37:39 +0200 Subject: [PATCH 24/33] squash! --- .azure-pipelines/common/build.yml | 16 - .azure-pipelines/common/lint.yml | 10 - .azure-pipelines/common/package.yml | 26 - .azure-pipelines/common/sbom.yml | 13 - .azure-pipelines/common/test.yml | 32 - .../compliance/CredScanSuppressions.json | 45 - .../compliance/PoliCheckExclusions.xml | 10 - .azure-pipelines/compliance/compliance.yml | 36 - .azure-pipelines/linux/xvfb.init | 56 - .azure-pipelines/main.yml | 54 - .github/CODEOWNERS | 1 - .github/workflows/bump-version-pr.yaml | 30 - .github/workflows/feature-request.yml | 43 - .github/workflows/info-needed-closer.yml | 27 - .github/workflows/locker.yml | 24 - .husky/pre-commit | 4 - Source/AzureDBExperiences.ts | 250 +- Source/DatabasesFileSystem.ts | 147 +- Source/ParsedConnectionString.ts | 36 +- Source/azureAccountUtils.ts | 27 +- .../api/DatabaseAccountTreeItemInternal.ts | 220 +- .../commands/api/DatabaseTreeItemInternal.ts | 93 +- Source/commands/api/apiCache.ts | 82 +- Source/commands/api/findTreeItem.ts | 355 +- Source/commands/api/pickTreeItem.ts | 220 +- Source/commands/api/revealTreeItem.ts | 29 +- .../DatabaseAccountDeleteStep.ts | 14 +- .../IDeleteWizardContext.ts | 25 +- .../deleteCosmosDBAccount.ts | 69 +- .../deleteDatabaseAccount.ts | 60 +- Source/commands/importDocuments.ts | 328 +- Source/constants.ts | 133 +- Source/docdb/docDBConnectionStrings.ts | 78 +- Source/docdb/getCosmosClient.ts | 35 +- Source/docdb/registerDocDBCommands.ts | 238 +- Source/docdb/tree/DocDBAccountTreeItem.ts | 56 +- Source/docdb/tree/DocDBAccountTreeItemBase.ts | 188 +- Source/docdb/tree/DocDBCollectionTreeItem.ts | 187 +- Source/docdb/tree/DocDBDatabaseTreeItem.ts | 31 +- .../docdb/tree/DocDBDatabaseTreeItemBase.ts | 329 +- Source/docdb/tree/DocDBDocumentTreeItem.ts | 286 +- Source/docdb/tree/DocDBDocumentsTreeItem.ts | 269 +- .../tree/DocDBStoredProcedureTreeItem.ts | 134 +- .../tree/DocDBStoredProceduresTreeItem.ts | 216 +- Source/docdb/tree/DocDBTreeItemBase.ts | 79 +- Source/docdb/tree/DocDBUtils.ts | 2 +- Source/docdb/tree/IDocDBTreeRoot.ts | 9 +- Source/extension.ts | 592 +- Source/extensionVariables.ts | 61 +- Source/getExtensionApi.ts | 41 +- Source/graph/gremlinEndpoints.ts | 74 +- Source/graph/registerGraphCommands.ts | 125 +- Source/graph/tree/GraphAccountTreeItem.ts | 87 +- Source/graph/tree/GraphCollectionTreeItem.ts | 181 +- Source/graph/tree/GraphDatabaseTreeItem.ts | 109 +- Source/graph/tree/GraphTreeItem.ts | 105 +- Source/mongo/MongoCommand.ts | 26 +- Source/mongo/MongoScrapbook.ts | 1135 +- Source/mongo/MongoShell.ts | 353 +- Source/mongo/connectToMongoClient.ts | 87 +- Source/mongo/errorListeners.ts | 98 +- Source/mongo/grammar/mongoLexer.ts | 535 +- Source/mongo/grammar/mongoListener.ts | 36 +- Source/mongo/grammar/mongoParser.ts | 2994 +-- Source/mongo/grammar/mongoVisitor.ts | 32 +- Source/mongo/grammar/visitors.ts | 157 +- Source/mongo/languageClient.ts | 120 +- Source/mongo/languageServer.ts | 4 +- Source/mongo/mongoConnectionStrings.ts | 158 +- Source/mongo/registerMongoCommands.ts | 500 +- Source/mongo/services/IConnectionParams.ts | 6 +- .../mongo/services/MongoCodeLensProvider.ts | 130 +- .../mongo/services/completionItemProvider.ts | 1015 +- Source/mongo/services/languageService.ts | 193 +- Source/mongo/services/mongoScript.ts | 195 +- Source/mongo/services/schemaService.ts | 1336 +- Source/mongo/setConnectedNode.ts | 10 +- Source/mongo/tree/IMongoTreeRoot.ts | 3 +- Source/mongo/tree/MongoAccountTreeItem.ts | 307 +- Source/mongo/tree/MongoCollectionTreeItem.ts | 753 +- Source/mongo/tree/MongoDatabaseTreeItem.ts | 611 +- Source/mongo/tree/MongoDocumentTreeItem.ts | 182 +- .../abstract/AbstractPostgresClient.ts | 30 +- Source/postgres/abstract/models.ts | 73 +- .../postgres/commands/checkAuthentication.ts | 56 +- .../commands/configurePostgresFirewall.ts | 128 +- .../commands/connectPostgresDatabase.ts | 70 +- .../postgres/commands/copyConnectionString.ts | 76 +- .../commands/createPostgresDatabase.ts | 49 +- .../IPostgresQueryWizardContext.ts | 5 +- .../IPostgresFunctionQueryWizardContext.ts | 5 +- .../function/createPostgresFunctionQuery.ts | 22 +- .../function/steps/FunctionQueryCreateStep.ts | 24 +- .../FunctionQueryCustomReturnTypeStep.ts | 19 +- .../function/steps/FunctionQueryNameStep.ts | 25 +- .../steps/FunctionQueryReturnTypeStep.ts | 87 +- .../runPostgresQueryWizard.ts | 29 +- .../createPostgresStoredProcedureQuery.ts | 17 +- .../steps/StoredProcedureQueryCreateStep.ts | 20 +- .../steps/StoredProcedureQueryNameStep.ts | 23 +- .../createPostgresQuery/validateIdentifier.ts | 203 +- .../IPostgresServerWizardContext.ts | 34 +- .../steps/PostgresServerConfirmPWStep.ts | 40 +- .../steps/PostgresServerCreateStep.ts | 205 +- .../steps/PostgresServerCredPWStep.ts | 99 +- .../steps/PostgresServerCredUserStep.ts | 100 +- .../steps/PostgresServerNameStep.ts | 143 +- .../steps/PostgresServerSetCredentialsStep.ts | 84 +- .../steps/PostgresServerSkuStep.ts | 465 +- .../commands/deletePostgresDatabase.ts | 61 +- .../commands/deletePostgresFunction.ts | 57 +- .../postgres/commands/deletePostgresServer.ts | 37 +- .../commands/deletePostgresStoredProcedure.ts | 60 +- .../postgres/commands/deletePostgresTable.ts | 56 +- .../commands/enterPostgresCredentials.ts | 153 +- .../executePostgresQueryInDocument.ts | 127 +- .../postgres/commands/openPostgresFunction.ts | 23 +- .../commands/openPostgresStoredProcedure.ts | 24 +- .../commands/registerPostgresCommands.ts | 166 +- .../commands/setPostgresCredentials.ts | 44 +- Source/postgres/getClientConfig.ts | 187 +- .../postgres/getPostgresProcedureQueryRows.ts | 61 +- Source/postgres/getTables.ts | 34 +- Source/postgres/postgresConnectionStrings.ts | 123 +- Source/postgres/postgresConstants.ts | 6 +- Source/postgres/runPostgresQuery.ts | 21 +- .../services/PostgresCodeLensProvider.ts | 122 +- Source/postgres/showPostgresQuery.ts | 16 +- Source/postgres/tree/ClientConfigFactory.ts | 171 +- .../postgres/tree/PostgresColumnTreeItem.ts | 41 +- .../postgres/tree/PostgresDatabaseTreeItem.ts | 252 +- .../postgres/tree/PostgresFunctionTreeItem.ts | 70 +- .../tree/PostgresFunctionsTreeItem.ts | 70 +- .../tree/PostgresResourcesTreeItemBase.ts | 26 +- .../postgres/tree/PostgresServerTreeItem.ts | 611 +- .../tree/PostgresStoredProcedureTreeItem.ts | 68 +- .../tree/PostgresStoredProceduresTreeItem.ts | 74 +- Source/postgres/tree/PostgresTableTreeItem.ts | 92 +- .../postgres/tree/PostgresTablesTreeItem.ts | 81 +- Source/resolver/AppResolver.ts | 149 +- Source/resolver/DatabaseWorkspaceProvider.ts | 48 +- .../ResolvedDatabaseAccountResource.ts | 117 +- .../resolver/ResolvedDocDBAccountResource.ts | 63 +- .../resolver/ResolvedMongoAccountResource.ts | 22 +- .../ResolvedPostgresServerResource.ts | 79 +- Source/table/tree/TableAccountTreeItem.ts | 50 +- Source/tree/AttachedAccountsTreeItem.ts | 973 +- .../tree/AzureAccountTreeItemWithAttached.ts | 65 +- Source/tree/AzureDBAPIStep.ts | 159 +- .../CosmosDBAccountCapacityStep.ts | 73 +- .../CosmosDBAccountCreateStep.ts | 130 +- .../CosmosDBAccountNameStep.ts | 85 +- .../ICosmosDBWizardContext.ts | 24 +- Source/tree/IAzureDBWizardContext.ts | 10 +- Source/tree/SubscriptionTreeItem.ts | 460 +- Source/utils/InteractiveChildProcess.ts | 336 +- Source/utils/activityUtils.ts | 13 +- Source/utils/array.ts | 18 +- Source/utils/azureClients.ts | 39 +- Source/utils/azureUtils.ts | 12 +- Source/utils/cp.ts | 17 +- Source/utils/getIp.ts | 106 +- Source/utils/getSecretStorageKey.ts | 2 +- Source/utils/improveError.ts | 14 +- Source/utils/localize.ts | 2 +- Source/utils/nonNull.ts | 49 +- Source/utils/openUrl.ts | 8 +- Source/utils/randomUtils.ts | 17 +- Source/utils/settingUtils.ts | 98 +- Source/utils/timeout.ts | 70 +- Source/utils/vscodeUtils.ts | 180 +- Source/utils/workspacUtils.ts | 21 +- Source/utils/wrapError.ts | 26 +- Source/vscode-cosmosdb.api.d.ts | 154 +- Source/vscode-cosmosdbgraph.api.d.ts | 26 +- package-lock.json | 21347 ---------------- package.json | 2210 +- src/AzureDBExperiences.ts | 118 - src/DatabasesFileSystem.ts | 77 - src/ParsedConnectionString.ts | 28 - src/azureAccountUtils.ts | 31 - .../api/DatabaseAccountTreeItemInternal.ts | 106 - src/commands/api/DatabaseTreeItemInternal.ts | 42 - src/commands/api/apiCache.ts | 46 - src/commands/api/findTreeItem.ts | 146 - src/commands/api/pickTreeItem.ts | 100 - src/commands/api/revealTreeItem.ts | 16 - .../DatabaseAccountDeleteStep.ts | 19 - .../IDeleteWizardContext.ts | 13 - .../deleteCosmosDBAccount.ts | 32 - .../deleteDatabaseAccount.ts | 37 - src/commands/importDocuments.ts | 163 - src/constants.ts | 136 - src/docdb/docDBConnectionStrings.ts | 42 - src/docdb/getCosmosClient.ts | 19 - src/docdb/registerDocDBCommands.ts | 104 - src/docdb/tree/DocDBAccountTreeItem.ts | 37 - src/docdb/tree/DocDBAccountTreeItemBase.ts | 95 - src/docdb/tree/DocDBCollectionTreeItem.ts | 92 - src/docdb/tree/DocDBDatabaseTreeItem.ts | 22 - src/docdb/tree/DocDBDatabaseTreeItemBase.ts | 161 - src/docdb/tree/DocDBDocumentTreeItem.ts | 133 - src/docdb/tree/DocDBDocumentsTreeItem.ts | 129 - .../tree/DocDBStoredProcedureTreeItem.ts | 76 - .../tree/DocDBStoredProceduresTreeItem.ts | 97 - src/docdb/tree/DocDBTreeItemBase.ts | 55 - src/docdb/tree/DocDBUtils.ts | 12 - src/docdb/tree/IDocDBTreeRoot.ts | 14 - src/extension.ts | 215 - src/extensionVariables.ts | 51 - src/getExtensionApi.ts | 31 - src/graph/gremlinEndpoints.ts | 47 - src/graph/registerGraphCommands.ts | 62 - src/graph/tree/GraphAccountTreeItem.ts | 45 - src/graph/tree/GraphCollectionTreeItem.ts | 87 - src/graph/tree/GraphDatabaseTreeItem.ts | 65 - src/graph/tree/GraphTreeItem.ts | 56 - src/mongo/MongoCommand.ts | 24 - src/mongo/MongoScrapbook.ts | 491 - src/mongo/MongoShell.ts | 187 - src/mongo/connectToMongoClient.ts | 49 - src/mongo/errorListeners.ts | 67 - src/mongo/grammar/mongo.tokens | 36 - src/mongo/grammar/mongoLexer.tokens | 36 - src/mongo/grammar/mongoLexer.ts | 247 - src/mongo/grammar/mongoListener.ts | 208 - src/mongo/grammar/mongoParser.ts | 1466 -- src/mongo/grammar/mongoVisitor.ts | 143 - src/mongo/grammar/visitors.ts | 83 - src/mongo/languageClient.ts | 58 - src/mongo/languageServer.ts | 31 - src/mongo/mongoConnectionStrings.ts | 104 - src/mongo/registerMongoCommands.ts | 223 - src/mongo/services/IConnectionParams.ts | 10 - src/mongo/services/MongoCodeLensProvider.ts | 75 - src/mongo/services/completionItemProvider.ts | 439 - src/mongo/services/languageService.ts | 90 - src/mongo/services/mongoScript.ts | 101 - src/mongo/services/schemaService.ts | 628 - src/mongo/setConnectedNode.ts | 13 - src/mongo/tree/IMongoTreeRoot.ts | 9 - src/mongo/tree/MongoAccountTreeItem.ts | 140 - src/mongo/tree/MongoCollectionTreeItem.ts | 320 - src/mongo/tree/MongoDatabaseTreeItem.ts | 258 - src/mongo/tree/MongoDocumentTreeItem.ts | 97 - .../abstract/AbstractPostgresClient.ts | 23 - src/postgres/abstract/models.ts | 55 - src/postgres/commands/checkAuthentication.ts | 36 - .../commands/configurePostgresFirewall.ts | 69 - .../commands/connectPostgresDatabase.ts | 39 - src/postgres/commands/copyConnectionString.ts | 36 - .../commands/createPostgresDatabase.ts | 26 - .../IPostgresQueryWizardContext.ts | 12 - .../IPostgresFunctionQueryWizardContext.ts | 10 - .../function/createPostgresFunctionQuery.ts | 23 - .../function/steps/FunctionQueryCreateStep.ts | 31 - .../FunctionQueryCustomReturnTypeStep.ts | 18 - .../function/steps/FunctionQueryNameStep.ts | 22 - .../steps/FunctionQueryReturnTypeStep.ts | 50 - .../runPostgresQueryWizard.ts | 23 - .../createPostgresStoredProcedureQuery.ts | 20 - .../steps/StoredProcedureQueryCreateStep.ts | 30 - .../steps/StoredProcedureQueryNameStep.ts | 22 - .../createPostgresQuery/validateIdentifier.ts | 113 - .../IPostgresServerWizardContext.ts | 24 - .../steps/PostgresServerConfirmPWStep.ts | 31 - .../steps/PostgresServerCreateStep.ts | 104 - .../steps/PostgresServerCredPWStep.ts | 53 - .../steps/PostgresServerCredUserStep.ts | 48 - .../steps/PostgresServerNameStep.ts | 60 - .../steps/PostgresServerSetCredentialsStep.ts | 46 - .../steps/PostgresServerSkuStep.ts | 250 - .../commands/deletePostgresDatabase.ts | 30 - .../commands/deletePostgresFunction.ts | 29 - src/postgres/commands/deletePostgresServer.ts | 22 - .../commands/deletePostgresStoredProcedure.ts | 29 - src/postgres/commands/deletePostgresTable.ts | 28 - .../commands/enterPostgresCredentials.ts | 85 - .../executePostgresQueryInDocument.ts | 65 - src/postgres/commands/openPostgresFunction.ts | 21 - .../commands/openPostgresStoredProcedure.ts | 21 - .../commands/registerPostgresCommands.ts | 82 - .../commands/setPostgresCredentials.ts | 32 - src/postgres/getClientConfig.ts | 172 - src/postgres/getPostgresProcedureQueryRows.ts | 58 - src/postgres/getTables.ts | 34 - src/postgres/postgresConnectionStrings.ts | 74 - src/postgres/postgresConstants.ts | 8 - src/postgres/runPostgresQuery.ts | 19 - .../services/PostgresCodeLensProvider.ts | 66 - src/postgres/showPostgresQuery.ts | 14 - src/postgres/tree/ClientConfigFactory.ts | 86 - src/postgres/tree/PostgresColumnTreeItem.ts | 33 - src/postgres/tree/PostgresDatabaseTreeItem.ts | 115 - src/postgres/tree/PostgresFunctionTreeItem.ts | 48 - .../tree/PostgresFunctionsTreeItem.ts | 46 - .../tree/PostgresResourcesTreeItemBase.ts | 27 - src/postgres/tree/PostgresServerTreeItem.ts | 252 - .../tree/PostgresStoredProcedureTreeItem.ts | 48 - .../tree/PostgresStoredProceduresTreeItem.ts | 46 - src/postgres/tree/PostgresTableTreeItem.ts | 56 - src/postgres/tree/PostgresTablesTreeItem.ts | 51 - src/resolver/AppResolver.ts | 71 - src/resolver/DatabaseWorkspaceProvider.ts | 33 - .../ResolvedDatabaseAccountResource.ts | 57 - src/resolver/ResolvedDocDBAccountResource.ts | 32 - src/resolver/ResolvedMongoAccountResource.ts | 20 - .../ResolvedPostgresServerResource.ts | 48 - src/table/tree/TableAccountTreeItem.ts | 39 - src/tree/AttachedAccountsTreeItem.ts | 420 - src/tree/AzureAccountTreeItemWithAttached.ts | 36 - src/tree/AzureDBAPIStep.ts | 76 - .../CosmosDBAccountCapacityStep.ts | 40 - .../CosmosDBAccountCreateStep.ts | 63 - .../CosmosDBAccountNameStep.ts | 49 - .../ICosmosDBWizardContext.ts | 19 - src/tree/IAzureDBWizardContext.ts | 14 - src/tree/SubscriptionTreeItem.ts | 158 - src/utils/InteractiveChildProcess.ts | 176 - src/utils/activityUtils.ts | 15 - src/utils/array.ts | 14 - src/utils/azureClients.ts | 24 - src/utils/azureUtils.ts | 14 - src/utils/cp.ts | 14 - src/utils/getIp.ts | 61 - src/utils/getSecretStorageKey.ts | 8 - src/utils/improveError.ts | 17 - src/utils/localize.ts | 8 - src/utils/nonNull.ts | 41 - src/utils/openUrl.ts | 13 - src/utils/randomUtils.ts | 17 - src/utils/settingUtils.ts | 62 - src/utils/timeout.ts | 51 - src/utils/vscodeUtils.ts | 103 - src/utils/workspacUtils.ts | 18 - src/utils/wrapError.ts | 24 - src/vscode-cosmosdb.api.d.ts | 96 - src/vscode-cosmosdbgraph.api.d.ts | 29 - test/.eslintrc.js | 6 - test/attachedAccountsTreeItem.test.ts | 27 - test/docDBConnectionStrings.test.ts | 61 - test/documentLabel.test.ts | 29 - test/global.test.ts | 20 - test/improveError.test.ts | 24 - test/index.ts | 55 - test/mongoConnectionStrings.test.ts | 165 - test/mongoGetCommand.test.ts | 1138 - test/mongoShell.test.ts | 288 - test/postgresConnectionStrings.test.ts | 30 - test/runTest.ts | 46 - test/runWithSetting.ts | 24 - test/test.code-workspace | 8 - test/timeout.test.ts | 120 - test/unit/DocDBUtils.test.ts | 16 - test/unit/getClientConfig.test.ts | 182 - test/util/getIp.test.ts | 45 - test/util/setEnvironmentVariables.test.ts | 36 - test/util/setEnvironmentVariables.ts | 35 - test/wrapError.test.ts | 53 - 359 files changed, 11500 insertions(+), 53689 deletions(-) delete mode 100644 .azure-pipelines/common/build.yml delete mode 100644 .azure-pipelines/common/lint.yml delete mode 100644 .azure-pipelines/common/package.yml delete mode 100644 .azure-pipelines/common/sbom.yml delete mode 100644 .azure-pipelines/common/test.yml delete mode 100644 .azure-pipelines/compliance/CredScanSuppressions.json delete mode 100644 .azure-pipelines/compliance/PoliCheckExclusions.xml delete mode 100644 .azure-pipelines/compliance/compliance.yml delete mode 100644 .azure-pipelines/linux/xvfb.init delete mode 100644 .azure-pipelines/main.yml delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/bump-version-pr.yaml delete mode 100644 .github/workflows/feature-request.yml delete mode 100644 .github/workflows/info-needed-closer.yml delete mode 100644 .github/workflows/locker.yml delete mode 100755 .husky/pre-commit delete mode 100644 package-lock.json delete mode 100644 src/AzureDBExperiences.ts delete mode 100644 src/DatabasesFileSystem.ts delete mode 100644 src/ParsedConnectionString.ts delete mode 100644 src/azureAccountUtils.ts delete mode 100644 src/commands/api/DatabaseAccountTreeItemInternal.ts delete mode 100644 src/commands/api/DatabaseTreeItemInternal.ts delete mode 100644 src/commands/api/apiCache.ts delete mode 100644 src/commands/api/findTreeItem.ts delete mode 100644 src/commands/api/pickTreeItem.ts delete mode 100644 src/commands/api/revealTreeItem.ts delete mode 100644 src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts delete mode 100644 src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts delete mode 100644 src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts delete mode 100644 src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts delete mode 100644 src/commands/importDocuments.ts delete mode 100644 src/constants.ts delete mode 100644 src/docdb/docDBConnectionStrings.ts delete mode 100644 src/docdb/getCosmosClient.ts delete mode 100644 src/docdb/registerDocDBCommands.ts delete mode 100644 src/docdb/tree/DocDBAccountTreeItem.ts delete mode 100644 src/docdb/tree/DocDBAccountTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBCollectionTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDatabaseTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDatabaseTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBDocumentTreeItem.ts delete mode 100644 src/docdb/tree/DocDBDocumentsTreeItem.ts delete mode 100644 src/docdb/tree/DocDBStoredProcedureTreeItem.ts delete mode 100644 src/docdb/tree/DocDBStoredProceduresTreeItem.ts delete mode 100644 src/docdb/tree/DocDBTreeItemBase.ts delete mode 100644 src/docdb/tree/DocDBUtils.ts delete mode 100644 src/docdb/tree/IDocDBTreeRoot.ts delete mode 100644 src/extension.ts delete mode 100644 src/extensionVariables.ts delete mode 100644 src/getExtensionApi.ts delete mode 100644 src/graph/gremlinEndpoints.ts delete mode 100644 src/graph/registerGraphCommands.ts delete mode 100644 src/graph/tree/GraphAccountTreeItem.ts delete mode 100644 src/graph/tree/GraphCollectionTreeItem.ts delete mode 100644 src/graph/tree/GraphDatabaseTreeItem.ts delete mode 100644 src/graph/tree/GraphTreeItem.ts delete mode 100644 src/mongo/MongoCommand.ts delete mode 100644 src/mongo/MongoScrapbook.ts delete mode 100644 src/mongo/MongoShell.ts delete mode 100644 src/mongo/connectToMongoClient.ts delete mode 100644 src/mongo/errorListeners.ts delete mode 100644 src/mongo/grammar/mongo.tokens delete mode 100644 src/mongo/grammar/mongoLexer.tokens delete mode 100644 src/mongo/grammar/mongoLexer.ts delete mode 100644 src/mongo/grammar/mongoListener.ts delete mode 100644 src/mongo/grammar/mongoParser.ts delete mode 100644 src/mongo/grammar/mongoVisitor.ts delete mode 100644 src/mongo/grammar/visitors.ts delete mode 100644 src/mongo/languageClient.ts delete mode 100644 src/mongo/languageServer.ts delete mode 100644 src/mongo/mongoConnectionStrings.ts delete mode 100644 src/mongo/registerMongoCommands.ts delete mode 100644 src/mongo/services/IConnectionParams.ts delete mode 100644 src/mongo/services/MongoCodeLensProvider.ts delete mode 100644 src/mongo/services/completionItemProvider.ts delete mode 100644 src/mongo/services/languageService.ts delete mode 100644 src/mongo/services/mongoScript.ts delete mode 100644 src/mongo/services/schemaService.ts delete mode 100644 src/mongo/setConnectedNode.ts delete mode 100644 src/mongo/tree/IMongoTreeRoot.ts delete mode 100644 src/mongo/tree/MongoAccountTreeItem.ts delete mode 100644 src/mongo/tree/MongoCollectionTreeItem.ts delete mode 100644 src/mongo/tree/MongoDatabaseTreeItem.ts delete mode 100644 src/mongo/tree/MongoDocumentTreeItem.ts delete mode 100644 src/postgres/abstract/AbstractPostgresClient.ts delete mode 100644 src/postgres/abstract/models.ts delete mode 100644 src/postgres/commands/checkAuthentication.ts delete mode 100644 src/postgres/commands/configurePostgresFirewall.ts delete mode 100644 src/postgres/commands/connectPostgresDatabase.ts delete mode 100644 src/postgres/commands/copyConnectionString.ts delete mode 100644 src/postgres/commands/createPostgresDatabase.ts delete mode 100644 src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts delete mode 100644 src/postgres/commands/createPostgresQuery/validateIdentifier.ts delete mode 100644 src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts delete mode 100644 src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts delete mode 100644 src/postgres/commands/deletePostgresDatabase.ts delete mode 100644 src/postgres/commands/deletePostgresFunction.ts delete mode 100644 src/postgres/commands/deletePostgresServer.ts delete mode 100644 src/postgres/commands/deletePostgresStoredProcedure.ts delete mode 100644 src/postgres/commands/deletePostgresTable.ts delete mode 100644 src/postgres/commands/enterPostgresCredentials.ts delete mode 100644 src/postgres/commands/executePostgresQueryInDocument.ts delete mode 100644 src/postgres/commands/openPostgresFunction.ts delete mode 100644 src/postgres/commands/openPostgresStoredProcedure.ts delete mode 100644 src/postgres/commands/registerPostgresCommands.ts delete mode 100644 src/postgres/commands/setPostgresCredentials.ts delete mode 100644 src/postgres/getClientConfig.ts delete mode 100644 src/postgres/getPostgresProcedureQueryRows.ts delete mode 100644 src/postgres/getTables.ts delete mode 100644 src/postgres/postgresConnectionStrings.ts delete mode 100644 src/postgres/postgresConstants.ts delete mode 100644 src/postgres/runPostgresQuery.ts delete mode 100644 src/postgres/services/PostgresCodeLensProvider.ts delete mode 100644 src/postgres/showPostgresQuery.ts delete mode 100644 src/postgres/tree/ClientConfigFactory.ts delete mode 100644 src/postgres/tree/PostgresColumnTreeItem.ts delete mode 100644 src/postgres/tree/PostgresDatabaseTreeItem.ts delete mode 100644 src/postgres/tree/PostgresFunctionTreeItem.ts delete mode 100644 src/postgres/tree/PostgresFunctionsTreeItem.ts delete mode 100644 src/postgres/tree/PostgresResourcesTreeItemBase.ts delete mode 100644 src/postgres/tree/PostgresServerTreeItem.ts delete mode 100644 src/postgres/tree/PostgresStoredProcedureTreeItem.ts delete mode 100644 src/postgres/tree/PostgresStoredProceduresTreeItem.ts delete mode 100644 src/postgres/tree/PostgresTableTreeItem.ts delete mode 100644 src/postgres/tree/PostgresTablesTreeItem.ts delete mode 100644 src/resolver/AppResolver.ts delete mode 100644 src/resolver/DatabaseWorkspaceProvider.ts delete mode 100644 src/resolver/ResolvedDatabaseAccountResource.ts delete mode 100644 src/resolver/ResolvedDocDBAccountResource.ts delete mode 100644 src/resolver/ResolvedMongoAccountResource.ts delete mode 100644 src/resolver/ResolvedPostgresServerResource.ts delete mode 100644 src/table/tree/TableAccountTreeItem.ts delete mode 100644 src/tree/AttachedAccountsTreeItem.ts delete mode 100644 src/tree/AzureAccountTreeItemWithAttached.ts delete mode 100644 src/tree/AzureDBAPIStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts delete mode 100644 src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts delete mode 100644 src/tree/IAzureDBWizardContext.ts delete mode 100644 src/tree/SubscriptionTreeItem.ts delete mode 100644 src/utils/InteractiveChildProcess.ts delete mode 100644 src/utils/activityUtils.ts delete mode 100644 src/utils/array.ts delete mode 100644 src/utils/azureClients.ts delete mode 100644 src/utils/azureUtils.ts delete mode 100644 src/utils/cp.ts delete mode 100644 src/utils/getIp.ts delete mode 100644 src/utils/getSecretStorageKey.ts delete mode 100644 src/utils/improveError.ts delete mode 100644 src/utils/localize.ts delete mode 100644 src/utils/nonNull.ts delete mode 100644 src/utils/openUrl.ts delete mode 100644 src/utils/randomUtils.ts delete mode 100644 src/utils/settingUtils.ts delete mode 100644 src/utils/timeout.ts delete mode 100644 src/utils/vscodeUtils.ts delete mode 100644 src/utils/workspacUtils.ts delete mode 100644 src/utils/wrapError.ts delete mode 100644 src/vscode-cosmosdb.api.d.ts delete mode 100644 src/vscode-cosmosdbgraph.api.d.ts delete mode 100644 test/.eslintrc.js delete mode 100644 test/attachedAccountsTreeItem.test.ts delete mode 100644 test/docDBConnectionStrings.test.ts delete mode 100644 test/documentLabel.test.ts delete mode 100644 test/global.test.ts delete mode 100644 test/improveError.test.ts delete mode 100644 test/index.ts delete mode 100644 test/mongoConnectionStrings.test.ts delete mode 100644 test/mongoGetCommand.test.ts delete mode 100644 test/mongoShell.test.ts delete mode 100644 test/postgresConnectionStrings.test.ts delete mode 100644 test/runTest.ts delete mode 100644 test/runWithSetting.ts delete mode 100644 test/test.code-workspace delete mode 100644 test/timeout.test.ts delete mode 100644 test/unit/DocDBUtils.test.ts delete mode 100644 test/unit/getClientConfig.test.ts delete mode 100644 test/util/getIp.test.ts delete mode 100644 test/util/setEnvironmentVariables.test.ts delete mode 100644 test/util/setEnvironmentVariables.ts delete mode 100644 test/wrapError.test.ts diff --git a/.azure-pipelines/common/build.yml b/.azure-pipelines/common/build.yml deleted file mode 100644 index d287b9eb2..000000000 --- a/.azure-pipelines/common/build.yml +++ /dev/null @@ -1,16 +0,0 @@ -steps: -- task: NodeTool@0 - displayName: 'Use Node 14.x' - inputs: - versionSpec: 14.x - -- task: Npm@1 - displayName: 'npm ci' - inputs: - command: ci - -- task: Npm@1 - displayName: 'Build' - inputs: - command: custom - customCommand: run build diff --git a/.azure-pipelines/common/lint.yml b/.azure-pipelines/common/lint.yml deleted file mode 100644 index 66d82cb8b..000000000 --- a/.azure-pipelines/common/lint.yml +++ /dev/null @@ -1,10 +0,0 @@ -steps: -- task: Npm@1 - displayName: 'Lint' - inputs: - command: custom - customCommand: run lint - -- task: ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - condition: ne(variables['System.PullRequest.IsFork'], 'True') diff --git a/.azure-pipelines/common/package.yml b/.azure-pipelines/common/package.yml deleted file mode 100644 index 13555193e..000000000 --- a/.azure-pipelines/common/package.yml +++ /dev/null @@ -1,26 +0,0 @@ -steps: -- task: Npm@1 - displayName: 'cleanReadme' - inputs: - command: custom - customCommand: run cleanReadme - -- task: Npm@1 - displayName: 'Package' - inputs: - command: custom - customCommand: run package - -- task: CopyFiles@2 - displayName: 'Copy vsix to staging directory' - inputs: - Contents: '**/*.vsix' - TargetFolder: '$(build.artifactstagingdirectory)' - -- task: PublishBuildArtifacts@1 - displayName: 'Publish artifacts: vsix' - inputs: - PathtoPublish: '$(build.artifactstagingdirectory)' - ArtifactName: vsix - # Only publish vsix from linux build since we use this to release and want to stay consistent - condition: and(eq(variables['Agent.OS'], 'Linux'), ne(variables['System.PullRequest.IsFork'], 'True')) diff --git a/.azure-pipelines/common/sbom.yml b/.azure-pipelines/common/sbom.yml deleted file mode 100644 index fa7c4cf28..000000000 --- a/.azure-pipelines/common/sbom.yml +++ /dev/null @@ -1,13 +0,0 @@ -steps: - - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: "SBoM Generation Task" - inputs: - BuildDropPath: "$(Build.ArtifactStagingDirectory)" - condition: ne(variables['System.PullRequest.IsFork'], 'True') - - - task: PublishBuildArtifacts@1 - displayName: "Publish artifacts: sbom" - inputs: - PathtoPublish: "$(Build.ArtifactStagingDirectory)/_manifest" - ArtifactName: _manifest - condition: ne(variables['System.PullRequest.IsFork'], 'True') diff --git a/.azure-pipelines/common/test.yml b/.azure-pipelines/common/test.yml deleted file mode 100644 index 9e4a65629..000000000 --- a/.azure-pipelines/common/test.yml +++ /dev/null @@ -1,32 +0,0 @@ -steps: -- script: | - sudo cp .azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - displayName: 'Start X Virtual Frame Buffer' - condition: eq(variables['Agent.OS'], 'Linux') - -- task: Npm@1 - displayName: 'Test' - inputs: - command: custom - customCommand: test - env: - SERVICE_PRINCIPAL_CLIENT_ID: $(SERVICE_PRINCIPAL_CLIENT_ID) - SERVICE_PRINCIPAL_SECRET: $(SERVICE_PRINCIPAL_SECRET) - SERVICE_PRINCIPAL_DOMAIN: $(SERVICE_PRINCIPAL_DOMAIN) - DISPLAY: :10 # Only necessary for linux test - -- task: Npm@1 - displayName: 'Unit Test' - inputs: - command: custom - customCommand: run unittest - -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '*-results.xml' - testRunTitle: '$(Agent.OS)' - condition: succeededOrFailed() diff --git a/.azure-pipelines/compliance/CredScanSuppressions.json b/.azure-pipelines/compliance/CredScanSuppressions.json deleted file mode 100644 index a3567c7ec..000000000 --- a/.azure-pipelines/compliance/CredScanSuppressions.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "tool": "Credential Scanner", - "suppressions": [ - { - "folder": "node_modules\\", - "_justification": "No need to scan external node modules." - }, - { - "file": "out\\test\\docDBConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "out\\test\\mongoConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "test\\docDBConnectionStrings.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "test\\mongoConnectionStrings.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\test\\docDBConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\test\\mongoConnectionStrings.test.js", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\extension.bundle.js.map", - "_justification": "Should be covered by scanning the pre-bundled files and it's unclear why the 'map' file in particular is getting flagged." - }, - { - "file": "test\\mongoGetCommand.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "dist\\mongo-languageServer.bundle.js.map", - "_justification": "Should be covered by scanning the pre-bundled files and it's unclear why the 'map' file in particular is getting flagged." - } - ] -} diff --git a/.azure-pipelines/compliance/PoliCheckExclusions.xml b/.azure-pipelines/compliance/PoliCheckExclusions.xml deleted file mode 100644 index 8188f1d5f..000000000 --- a/.azure-pipelines/compliance/PoliCheckExclusions.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - NODE_MODULES|DIST - - - - - - - diff --git a/.azure-pipelines/compliance/compliance.yml b/.azure-pipelines/compliance/compliance.yml deleted file mode 100644 index f10805317..000000000 --- a/.azure-pipelines/compliance/compliance.yml +++ /dev/null @@ -1,36 +0,0 @@ -steps: -- task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@1 - displayName: 'Run PoliCheck' - inputs: - targetType: F # search files and folders - optionsUEPATH: '$(Build.SourcesDirectory)/.azure-pipelines/compliance/PoliCheckExclusions.xml' - continueOnError: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@2 - displayName: 'Run CredScan' - inputs: - toolMajorVersion: V2 - suppressionsFile: '$(Build.SourcesDirectory)/.azure-pipelines/compliance/CredScanSuppressions.json' - debugMode: true # Needed to suppress folders - folderSuppression: true - continueOnError: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 - displayName: 'AntiMalware Scanner' - inputs: - FileDirPath: '$(Build.SourcesDirectory)' - EnableServices: true - continueOnError: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 - displayName: 'Publish Security Analysis Logs' - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') - -- task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1 - displayName: 'Post Analysis' - inputs: - AllTools: true - condition: eq(variables['ENABLE_COMPLIANCE'], 'true') diff --git a/.azure-pipelines/linux/xvfb.init b/.azure-pipelines/linux/xvfb.init deleted file mode 100644 index f2f5e422d..000000000 --- a/.azure-pipelines/linux/xvfb.init +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# -# COPIED FROM https://github.com/microsoft/vscode/blob/01e9903967417ba243cec705445eef9ecbfebfea/build/azure-pipelines/linux/xvfb.init -# -# -# /etc/rc.d/init.d/xvfbd -# -# chkconfig: 345 95 28 -# description: Starts/Stops X Virtual Framebuffer server -# processname: Xvfb -# -### BEGIN INIT INFO -# Provides: xvfb -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Start xvfb at boot time -# Description: Enable xvfb provided by daemon. -### END INIT INFO - -[ "${NETWORKING}" = "no" ] && exit 0 - -PROG="/usr/bin/Xvfb" -PROG_OPTIONS=":10 -ac -screen 0 1024x768x24" -PROG_OUTPUT="/tmp/Xvfb.out" - -case "$1" in - start) - echo "Starting : X Virtual Frame Buffer " - $PROG $PROG_OPTIONS>>$PROG_OUTPUT 2>&1 & - disown -ar - ;; - stop) - echo "Shutting down : X Virtual Frame Buffer" - killproc $PROG - RETVAL=$? - [ $RETVAL -eq 0 ] && /bin/rm -f /var/lock/subsys/Xvfb - /var/run/Xvfb.pid - echo - ;; - restart|reload) - $0 stop - $0 start - RETVAL=$? - ;; - status) - status Xvfb - RETVAL=$? - ;; - *) - echo $"Usage: $0 (start|stop|restart|reload|status)" - exit 1 -esac - -exit $RETVAL diff --git a/.azure-pipelines/main.yml b/.azure-pipelines/main.yml deleted file mode 100644 index 8adaf3c97..000000000 --- a/.azure-pipelines/main.yml +++ /dev/null @@ -1,54 +0,0 @@ -variables: - ${{ if eq(variables['Build.Reason'], 'Schedule') }}: - ENABLE_LONG_RUNNING_TESTS: true - ENABLE_COMPLIANCE: true - -jobs: -- job: Windows - pool: - vmImage: windows-latest - steps: - - template: common/build.yml - - template: common/package.yml - - template: common/lint.yml - - template: compliance/compliance.yml # Only works on Windows - - template: common/test.yml - -- job: Linux - pool: - vmImage: ubuntu-latest - steps: - - template: common/build.yml - - template: common/package.yml - - template: common/sbom.yml # only generate on linux - - template: common/lint.yml - - template: common/test.yml - variables: - Codeql.Enabled: $[in(variables['Build.Reason'], 'Schedule')] # Enable CodeQL only on scheduled builds because it is slow - -- job: macOS - pool: - vmImage: macOS-latest - steps: - - template: common/build.yml - - template: common/package.yml - - template: common/lint.yml - - template: common/test.yml - -trigger: - branches: - include: - - '*' - -pr: - branches: - include: - - '*' - -schedules: -- cron: "30 10 * * *" - displayName: Nightly at 3:30 PT - always: true # Run even when there are no code changes - branches: - include: - - main diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index f426a03c5..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @Microsoft/vscodeazuretoolsdev diff --git a/.github/workflows/bump-version-pr.yaml b/.github/workflows/bump-version-pr.yaml deleted file mode 100644 index dec36e0a9..000000000 --- a/.github/workflows/bump-version-pr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Bump version after release - -# Run when release is published, or manually triggered -on: - release: - types: [published] - workflow_dispatch: - -jobs: - bump: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Bump version - id: bump - uses: alexweininger/bump-prerelease-version@v0.1.1 - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - title: ${{ env.MESSAGE }} - body: Automatically created by ${{ env.RUN_LINK }} - commit-message: ${{ env.MESSAGE }} - branch: bot/bump-${{ steps.bump.outputs.new-version }} - base: main - author: GitHub - env: - RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - MESSAGE: Bump version after release diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml deleted file mode 100644 index 94c0c5144..000000000 --- a/.github/workflows/feature-request.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Feature Request Manager -on: - issues: - types: [milestoned] - schedule: - - cron: 15 5 * * * # 10:15pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: actions/checkout@v3 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - run: npm install --production --prefix ./actions - - name: Run Feature Request Manager - if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') - uses: ./actions/feature-request - with: - token: ${{secrets.AZCODE_BOT_PAT}} - candidateMilestoneID: 28 - candidateMilestoneName: "Backlog Candidates" - backlogMilestoneID: 33 - featureRequestLabel: "feature" - upvotesRequired: 5 - numCommentsOverride: 10 - initComment: "This feature request is now a candidate for our backlog. The community has 240 days to upvote the issue. If it receives 5 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectComment: ":slightly_frowning_face: In the last 60 days, this issue has received less than 5 community upvotes and we closed it. Still a big Thank You to you for taking the time to create it! To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - rejectLabel: "out of scope" - warnComment: "This issue has become stale and is at risk of being closed. The community has 60 days to upvote the issue. If it receives 5 upvotes we will keep it open and take another look. If not, we will close it. To learn more about how we handle issues, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - labelsToExclude: "P0,P1" - acceptComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/azcodeissuetriaging).\n\nHappy Coding!" - warnDays: 60 - closeDays: 240 - milestoneDelaySeconds: 60 - diff --git a/.github/workflows/info-needed-closer.yml b/.github/workflows/info-needed-closer.yml deleted file mode 100644 index 9304007a4..000000000 --- a/.github/workflows/info-needed-closer.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Info Needed Closer -on: - schedule: - - cron: 30 5 * * * # 10:30pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Info Needed Closer - uses: ./actions/needs-more-info-closer - with: - token: ${{secrets.AZCODE_BOT_PAT}} - label: info-needed - closeDays: 14 - closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/azcodeissuereporting) guidelines.\n\nHappy Coding!" - pingDays: 80 - pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information." diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml deleted file mode 100644 index 050406703..000000000 --- a/.github/workflows/locker.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Locker -on: - schedule: - - cron: 0 5 * * * # 10:00pm PT - workflow_dispatch: - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "microsoft/vscode-github-triage-actions" - path: ./actions - ref: stable - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Run Locker - uses: ./actions/locker - with: - token: ${{secrets.AZCODE_BOT_PAT}} - daysSinceClose: 45 - daysSinceUpdate: 7 diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 901b4c3f8..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx vscode-sort-package-json diff --git a/Source/AzureDBExperiences.ts b/Source/AzureDBExperiences.ts index 97d2221cc..be9765dc6 100644 --- a/Source/AzureDBExperiences.ts +++ b/Source/AzureDBExperiences.ts @@ -3,202 +3,116 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "./utils/nonNull"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import { nonNullProp } from './utils/nonNull'; export enum API { - MongoDB = "MongoDB", - Graph = "Graph", - Table = "Table", - Core = "Core", - PostgresSingle = "PostgresSingle", - PostgresFlexible = "PostgresFlexible", + MongoDB = 'MongoDB', + Graph = 'Graph', + Table = 'Table', + Core = 'Core', + PostgresSingle = 'PostgresSingle', + PostgresFlexible = 'PostgresFlexible' } export enum DBAccountKind { - MongoDB = "MongoDB", - GlobalDocumentDB = "GlobalDocumentDB", + MongoDB = 'MongoDB', + GlobalDocumentDB = 'GlobalDocumentDB' } -export type CapabilityName = "EnableGremlin" | "EnableTable"; +export type CapabilityName = 'EnableGremlin' | 'EnableTable'; export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { - api: api, - shortName: api, - longName: api, - kind: DBAccountKind.GlobalDocumentDB, - tag: api, - }; - } - return info; + let info = experiencesMap.get(api); + if (!info) { + info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; + } + return info; } -export function getExperienceLabel( - databaseAccount: DatabaseAccountGetResults -): string { - const experience: Experience | undefined = - tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = ( - (databaseAccount && - databaseAccount.tags && - databaseAccount.tags.defaultExperience) - ); - const firstCapability = - databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ""); - return ( - defaultExperience || - firstCapabilityName || - nonNullProp(databaseAccount, "kind") - ); +export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { + + const experience: Experience | undefined = tryGetExperience(databaseAccount); + if (experience) { + return experience.shortName; + } + // Must be some new kind of resource that we aren't aware of. Try to get a decent label + const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); + const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; + const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); + return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); + } -export function tryGetExperience( - resource: DatabaseAccountGetResults -): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if ( - resource.capabilities?.find((cap) => cap.name === "EnableGremlin") - ) { - return GremlinExperience; - } else if ( - resource.capabilities?.find((cap) => cap.name === "EnableTable") - ) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; +export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { + // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type + if (resource.kind === DBAccountKind.MongoDB) { + return MongoExperience; + } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { + return GremlinExperience; + } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { + return TableExperience; + } else if (resource.capabilities?.length === 0) { + return CoreExperience; + } + + return undefined; } export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; + /** + * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) + */ + api: API; - longName: string; - shortName: string; - description?: string; + longName: string; + shortName: string; + description?: string; - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; + // These properties are what the portal actually looks at to determine the difference between APIs + kind?: DBAccountKind; + capability?: CapabilityName; - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; + // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) + tag?: string; } -export function getExperienceQuickPicks( - attached?: boolean -): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map((exp) => - getExperienceQuickPickForAttached(exp.api) - ); - } else { - return experiencesArray.map((exp) => getExperienceQuickPick(exp.api)); - } +export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { + if (attached) { + return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); + } else { + return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); + } } -export function getCosmosExperienceQuickPicks( - attached?: boolean -): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map((exp) => - getExperienceQuickPickForAttached(exp.api) - ); - } else { - return cosmosExperiencesArray.map((exp) => - getExperienceQuickPick(exp.api) - ); - } +export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { + if (attached) { + return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); + } else { + return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); + } } -export function getExperienceQuickPick( - api: API -): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; +export function getExperienceQuickPick(api: API): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.longName, description: exp.description, data: exp }; } -export function getExperienceQuickPickForAttached( - api: API -): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; +export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.shortName, description: exp.description, data: exp }; } // Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" // Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { - api: API.Core, - longName: "Core", - description: "(SQL)", - shortName: "SQL", - kind: DBAccountKind.GlobalDocumentDB, - tag: "Core (SQL)", -} as const; -export const MongoExperience: Experience = { - api: API.MongoDB, - longName: "Azure Cosmos DB for MongoDB API", - shortName: "MongoDB", - kind: DBAccountKind.MongoDB, - tag: "Azure Cosmos DB for MongoDB API", -} as const; -export const TableExperience: Experience = { - api: API.Table, - longName: "Azure Table", - shortName: "Table", - kind: DBAccountKind.GlobalDocumentDB, - capability: "EnableTable", - tag: "Azure Table", -} as const; -export const GremlinExperience: Experience = { - api: API.Graph, - longName: "Gremlin", - description: "(graph)", - shortName: "Gremlin", - kind: DBAccountKind.GlobalDocumentDB, - capability: "EnableGremlin", - tag: "Gremlin (graph)", -} as const; -const PostgresSingleExperience: Experience = { - api: API.PostgresSingle, - longName: "PostgreSQL Single Server", - shortName: "PostgreSQLSingle", -}; -const PostgresFlexibleExperience: Experience = { - api: API.PostgresFlexible, - longName: "PostgreSQL Flexible Server", - shortName: "PostgreSQLFlexible", -}; - -const cosmosExperiencesArray: Experience[] = [ - CoreExperience, - MongoExperience, - TableExperience, - GremlinExperience, -]; -const experiencesArray: Experience[] = [ - ...cosmosExperiencesArray, - PostgresSingleExperience, - PostgresFlexibleExperience, -]; -const experiencesMap = new Map( - experiencesArray.map((info: Experience): [API, Experience] => [ - info.api, - info, - ]) -); +export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; +export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; +export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; +export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; +const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; +const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; + +const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; +const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; +const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); diff --git a/Source/DatabasesFileSystem.ts b/Source/DatabasesFileSystem.ts index da2073ac0..93c2b4938 100644 --- a/Source/DatabasesFileSystem.ts +++ b/Source/DatabasesFileSystem.ts @@ -3,13 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeFileSystem, - AzExtTreeItem, - DialogResponses, - IActionContext, - UserCancelledError, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; import { FileChangeType } from "vscode-languageclient"; import { ext } from "./extensionVariables"; @@ -18,103 +12,66 @@ import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; import { getNodeEditorLabel } from "./utils/vscodeUtils"; export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; + id: string; + filePath: string; + cTime: number; + mTime: number; + getFileContent(context: IActionContext): Promise; + writeFileContent(context: IActionContext, data: string): Promise; } export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = "azureDatabases"; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; + public static scheme: string = 'azureDatabases'; + public scheme: string = DatabasesFileSystem.scheme; + private _showSaveConfirmation: boolean = true; - public async statImpl( - context: IActionContext, - node: IEditableTreeItem - ): Promise { - const size: number = Buffer.byteLength( - await node.getFileContent(context) - ); - return { - type: FileType.File, - ctime: node.cTime, - mtime: node.mTime, - size, - }; - } + public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { + const size: number = Buffer.byteLength(await node.getFileContent(context)); + return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; + } - public async readFileImpl( - context: IActionContext, - node: IEditableTreeItem - ): Promise { - return Buffer.from(await node.getFileContent(context)); - } + public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { + return Buffer.from(await node.getFileContent(context)); + } - public async writeFileImpl( - context: IActionContext, - node: IEditableTreeItem, - content: Uint8Array, - _originalUri: Uri - ): Promise { - const showSavePromptKey: string = "showSavePrompt"; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = "cosmosDB"; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if ( - this._showSaveConfirmation && - getWorkspaceSetting(showSavePromptKey, undefined, prefix) - ) { - const message: string = localize( - "saveConfirmation", - 'Saving "{0}" will update the entity "{1}" to the cloud.', - node.filePath, - nodeEditorLabel - ); - const result: MessageItem | undefined = - await context.ui.showWarningMessage( - message, - { stepName: "writeFile" }, - DialogResponses.upload, - DialogResponses.alwaysUpload, - DialogResponses.dontUpload - ); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError("dontUpload"); - } - } + public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { + const showSavePromptKey: string = 'showSavePrompt'; + // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" + const prefix: string = 'cosmosDB'; + const nodeEditorLabel: string = getNodeEditorLabel(node); + if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { + const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); + const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); + if (result === DialogResponses.alwaysUpload) { + await updateGlobalSetting(showSavePromptKey, false, prefix); + } else if (result === DialogResponses.dontUpload) { + throw new UserCancelledError('dontUpload'); + } + } - await node.writeFileContent(context, content.toString()); - await node.refresh(context); + await node.writeFileContent(context, content.toString()); + await node.refresh(context); - const updatedMessage: string = localize( - "updatedEntity", - 'Updated entity "{0}".', - nodeEditorLabel - ); - ext.outputChannel.appendLog(updatedMessage); - } + const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); + ext.outputChannel.appendLog(updatedMessage); + } - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } + public getFilePath(node: IEditableTreeItem): string { + return node.filePath; + } - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } + public async updateWithoutPrompt(uri: Uri): Promise { + const textDoc = await workspace.openTextDocument(uri); + this._showSaveConfirmation = false; + try { + await textDoc.save(); + } finally { + this._showSaveConfirmation = true; + } + } - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } + public fireChangedEvent(node: IEditableTreeItem): void { + node.mTime = Date.now(); + this.fireSoon({ type: FileChangeType.Changed, item: node }); + } } diff --git a/Source/ParsedConnectionString.ts b/Source/ParsedConnectionString.ts index 1619d6390..99654ef5a 100644 --- a/Source/ParsedConnectionString.ts +++ b/Source/ParsedConnectionString.ts @@ -4,27 +4,25 @@ *--------------------------------------------------------------------------------------------*/ export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; + public abstract readonly hostName: string; + public abstract readonly port: string; - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; + /** + * databaseName may be undefined if this is an account-level connection string + */ + public readonly databaseName: string | undefined; + public readonly connectionString: string; - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } + constructor(connectionString: string, databaseName: string | undefined) { + this.connectionString = connectionString; + this.databaseName = databaseName; + } - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } + public get accountId(): string { + return `${this.hostName}:${this.port}`; + } - public get fullId(): string { - return `${this.accountId}${ - this.databaseName ? "/" + this.databaseName : "" - }`; - } + public get fullId(): string { + return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; + } } diff --git a/Source/azureAccountUtils.ts b/Source/azureAccountUtils.ts index fbd474ae3..7f37da4cd 100644 --- a/Source/azureAccountUtils.ts +++ b/Source/azureAccountUtils.ts @@ -9,32 +9,23 @@ import { getApiExport } from "./getExtensionApi"; const azureAccountExtensionId = "ms-vscode.azure-account"; type AzureSession = { - userId: string; + userId: string; }; /** * @returns The user session of the signed-in azure account. */ -export async function getAzureAdUserSession(): Promise< - AzureSession | undefined -> { - const azureAccountExport = (await getApiExport( - azureAccountExtensionId - )) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; +export async function getAzureAdUserSession(): Promise { + const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; + return azureAccountExport.sessions?.[0]; } /** * Gets a function that can request an access token for a specified scope for the signed-in azure account. */ -export function getTokenFunction( - credentials: AzExtServiceClientCredentials, - scope: string -): () => Promise { - return async () => { - const getTokenResult = (await credentials.getToken(scope)) as - | { token: string } - | undefined; - return getTokenResult?.token ?? ""; - }; +export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { + return async () => { + const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; + return getTokenResult?.token ?? ""; + }; } diff --git a/Source/commands/api/DatabaseAccountTreeItemInternal.ts b/Source/commands/api/DatabaseAccountTreeItemInternal.ts index 6a5cebe8a..89a8c1164 100644 --- a/Source/commands/api/DatabaseAccountTreeItemInternal.ts +++ b/Source/commands/api/DatabaseAccountTreeItemInternal.ts @@ -3,146 +3,104 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { API } from "../../AzureDBExperiences"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { ParsedPostgresConnectionString } from "../../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { nonNullProp } from "../../utils/nonNull"; -import { DatabaseAccountTreeItem } from "../../vscode-cosmosdb.api"; +import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { API } from '../../AzureDBExperiences'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { nonNullProp } from '../../utils/nonNull'; +import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; -export class DatabaseAccountTreeItemInternal - implements DatabaseAccountTreeItem -{ - protected _parsedCS: ParsedConnectionString; - private _accountNode: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem - | undefined; +export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { + protected _parsedCS: ParsedConnectionString; + private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; - constructor( - parsedCS: ParsedConnectionString, - accountNode?: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem - ) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } + constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { + this._parsedCS = parsedCS; + this._accountNode = accountNode; + } - public get connectionString(): string { - return this._parsedCS.connectionString; - } + public get connectionString(): string { + return this._parsedCS.connectionString; + } - public get hostName(): string { - return this._parsedCS.hostName; - } + public get hostName(): string { + return this._parsedCS.hostName; + } - public get port(): string { - return this._parsedCS.port; - } + public get port(): string { + return this._parsedCS.port; + } - public get azureData(): - | { accountName: string; accountId: string } - | undefined { - if ( - this._accountNode instanceof MongoAccountTreeItem || - this._accountNode instanceof DocDBAccountTreeItemBase - ) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp( - this._accountNode.databaseAccount, - "name" - ), - accountId: this._accountNode.fullId, - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId, - }; - } - } - return undefined; - } + public get azureData(): { accountName: string, accountId: string } | undefined { + if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { + if (this._accountNode?.databaseAccount) { + return { + accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), + accountId: this._accountNode.fullId + }; + } + } else if (this._accountNode instanceof PostgresServerTreeItem) { + if (this._accountNode.azureName) { + return { + accountName: this._accountNode.azureName, + accountId: this._accountNode.fullId + }; + } + } + return undefined; + } - public get docDBData(): - | { masterKey: string; documentEndpoint: string } - | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey, - }; - } else { - return undefined; - } - } + public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { + if (this._accountNode instanceof DocDBAccountTreeItemBase) { + return { + documentEndpoint: this._accountNode.root.endpoint, + masterKey: this._accountNode.root.masterKey + }; + } else { + return undefined; + } + } - public get postgresData(): - | { username: string | undefined; password: string | undefined } - | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password, - }; - } else { - return undefined; - } - } + public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { + if (this._parsedCS instanceof ParsedPostgresConnectionString) { + const connectionString = this._parsedCS; + return { + username: connectionString.username, + password: connectionString.password + }; + } else { + return undefined; + } + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling( - "api.dbAccount.reveal", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal( - await this.getAccountNode(context) - ); - } - ); - } + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); + }); + } - protected async getAccountNode( - context: IActionContext - ): Promise< - MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem - > { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if ( - this._parsedCS instanceof ParsedPostgresConnectionString - ) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = - await ext.attachedAccountsNode.attachConnectionString( - context, - this.connectionString, - apiType - ); - } + protected async getAccountNode(context: IActionContext): Promise { + // If this._accountNode is undefined, attach a new node based on connection string + if (!this._accountNode) { - return this._accountNode; - } + let apiType: API; + if (this._parsedCS instanceof ParsedMongoConnectionString) { + apiType = API.MongoDB; + } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { + apiType = API.PostgresSingle; + } else { + apiType = API.Core; + } + this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); + } + + return this._accountNode; + } } diff --git a/Source/commands/api/DatabaseTreeItemInternal.ts b/Source/commands/api/DatabaseTreeItemInternal.ts index 8fa8389b2..9d6b0d140 100644 --- a/Source/commands/api/DatabaseTreeItemInternal.ts +++ b/Source/commands/api/DatabaseTreeItemInternal.ts @@ -3,71 +3,40 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { DatabaseTreeItem } from "../../vscode-cosmosdb.api"; -import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; +import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -export class DatabaseTreeItemInternal - extends DatabaseAccountTreeItemInternal - implements DatabaseTreeItem -{ - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; +export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { + public databaseName: string; + private _dbNode: AzExtTreeItem | undefined; - constructor( - parsedCS: ParsedConnectionString, - databaseName: string, - accountNode?: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem, - dbNode?: - | MongoDatabaseTreeItem - | DocDBDatabaseTreeItemBase - | PostgresDatabaseTreeItem - ) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } + constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { + super(parsedCS, accountNode); + this.databaseName = databaseName; + this._dbNode = dbNode; + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling( - "api.db.reveal", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const accountNode: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem = - await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = - await ext.rgApi.workspaceResourceTree.findTreeItem( - databaseId, - context - ); - } + const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); + if (!this._dbNode) { + const databaseId = `${accountNode.fullId}/${this.databaseName}`; + this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); + } - await ext.rgApi.workspaceResourceTreeView.reveal( - this._dbNode || accountNode - ); - } - ); - } + await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); + }); + } } diff --git a/Source/commands/api/apiCache.ts b/Source/commands/api/apiCache.ts index 9020478fd..30da342aa 100644 --- a/Source/commands/api/apiCache.ts +++ b/Source/commands/api/apiCache.ts @@ -3,68 +3,44 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParsedDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; -import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { - ParsedPostgresConnectionString, - parsePostgresConnectionString, -} from "../../postgres/postgresConnectionStrings"; -import { - DatabaseAccountTreeItem, - DatabaseTreeItem, -} from "../../vscode-cosmosdb.api"; +import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; +import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; +import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; /** * This cache is used to speed up api calls from other extensions to the Cosmos DB extension * For now, it only helps on a per-session basis */ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = - new Map(); +const sessionCache: Map = new Map(); -export function cacheTreeItem( - parsedCS: ParsedConnectionString, - treeItem: DatabaseAccountTreeItem | DatabaseTreeItem -): void { - sessionCache.set(parsedCS.fullId, treeItem); +export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { + sessionCache.set(parsedCS.fullId, treeItem); } -export function tryGetTreeItemFromCache( - parsedCS: ParsedConnectionString -): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); +export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { + return sessionCache.get(parsedCS.fullId); } -export function removeTreeItemFromCache( - expected: ParsedConnectionString -): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString( - value.connectionString, - value.hostName, - value.port, - undefined - ); - } else { - actual = new ParsedDocDBConnectionString( - value.connectionString, - value.hostName, - value.port, - undefined - ); - } - if (actual && actual.accountId === expected.accountId) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } +export function removeTreeItemFromCache(expected: ParsedConnectionString): void { + if (!expected.databaseName) { + // If parsedCS represents an account, remove the account and any databases that match that account + for (const [key, value] of sessionCache.entries()) { + let actual: ParsedConnectionString | undefined; + if (expected instanceof ParsedPostgresConnectionString) { + actual = parsePostgresConnectionString(value.connectionString); + } else if (expected instanceof ParsedMongoConnectionString) { + actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); + } else { + actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); + } + if (actual && (actual.accountId === expected.accountId)) { + sessionCache.delete(key); + } + } + } else { + sessionCache.delete(expected.fullId); + } } diff --git a/Source/commands/api/findTreeItem.ts b/Source/commands/api/findTreeItem.ts index d7e0f0d01..088413e52 100644 --- a/Source/commands/api/findTreeItem.ts +++ b/Source/commands/api/findTreeItem.ts @@ -3,223 +3,144 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { - createPostgresConnectionString, - parsePostgresConnectionString, -} from "../../postgres/postgresConnectionStrings"; -import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { SubscriptionTreeItem } from "../../tree/SubscriptionTreeItem"; -import { nonNullProp } from "../../utils/nonNull"; -import { - DatabaseAccountTreeItem, - DatabaseTreeItem, - TreeItemQuery, -} from "../../vscode-cosmosdb.api"; -import { cacheTreeItem, tryGetTreeItemFromCache } from "./apiCache"; -import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; - -export async function findTreeItem( - query: TreeItemQuery -): Promise { - return await callWithTelemetryAndErrorHandling( - "api.findTreeItem", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString( - postgresData.hostName, - postgresData.port, - postgresData.username, - postgresData.password, - postgresData.databaseName - ); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, "connectionString"); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = - await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = - tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = - await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts( - attachedDbAccounts, - parsedCS, - context, - maxTime - ); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = - await rootNode.getCachedChildren(context); - result = await searchDbAccounts( - dbAccounts, - parsedCS, - context, - maxTime - ); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal( - parsedCS, - parsedCS.databaseName - ); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - } - ); +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; +import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; +import { nonNullProp } from '../../utils/nonNull'; +import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; +import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; +import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; + +export async function findTreeItem(query: TreeItemQuery): Promise { + return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + + let parsedCS: ParsedConnectionString; + if (query.postgresData) { + const postgresData = query.postgresData; + const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); + parsedCS = parsePostgresConnectionString(connectionString); + } else { + const connectionString = nonNullProp(query, 'connectionString'); + if (/^mongodb[^:]*:\/\//i.test(connectionString)) { + parsedCS = await parseMongoConnectionString(connectionString); + } else if (/^postgres:\/\//i.test(connectionString)) { + parsedCS = parsePostgresConnectionString(connectionString); + } else { + parsedCS = parseDocDBConnectionString(connectionString); + } + } + + const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account + + // 1. Get result from cache if possible + let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); + + // 2. Search attached accounts (do this before subscriptions because it's faster) + if (!result) { + const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); + result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); + } + + // 3. Search subscriptions + if (!result) { + const rootNodes = await ext.rgApi.appResourceTree.getChildren(); + for (const rootNode of rootNodes) { + if (Date.now() > maxTime) { + break; + } + + if (rootNode instanceof SubscriptionTreeItem) { + const dbAccounts = await rootNode.getCachedChildren(context); + result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); + if (result) { + break; + } + } + } + } + + // 4. If all else fails, just attach a new node + if (!result) { + if (parsedCS.databaseName) { + result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); + } else { + result = new DatabaseAccountTreeItemInternal(parsedCS); + } + } + + cacheTreeItem(parsedCS, result); + + return result; + }); } -async function searchDbAccounts( - dbAccounts: AzExtTreeItem[], - expected: ParsedConnectionString, - context: IActionContext, - maxTime: number -): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString( - dbAccount.connectionString - ); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ( - (db instanceof MongoDatabaseTreeItem || - db instanceof DocDBDatabaseTreeItemBase) && - expected.databaseName === db.databaseName - ) { - return new DatabaseTreeItemInternal( - expected, - expected.databaseName, - dbAccount, - db - ); - } - if ( - db instanceof PostgresDatabaseTreeItem && - dbAccount instanceof PostgresServerTreeItem && - expected.databaseName === db.databaseName - ) { - const fullConnectionString = - await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal( - fullConnectionString, - expected.databaseName, - dbAccount, - db - ); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = - await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal( - fullConnectionString, - expected.databaseName, - dbAccount - ); - } else { - return new DatabaseTreeItemInternal( - expected, - expected.databaseName, - dbAccount - ); - } - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = - await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal( - fullConnectionString, - dbAccount - ); - } else { - return new DatabaseAccountTreeItemInternal( - expected, - dbAccount - ); - } - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; +async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { + try { + for (const dbAccount of dbAccounts) { + if (Date.now() > maxTime) { + return undefined; + } + + let actual: ParsedConnectionString; + if (dbAccount instanceof MongoAccountTreeItem) { + actual = await parseMongoConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof DocDBAccountTreeItemBase) { + actual = parseDocDBConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof PostgresServerTreeItem) { + actual = dbAccount.partialConnectionString; + } else { + return undefined; + } + + if (expected.accountId === actual.accountId) { + if (expected.databaseName) { + const dbs = await dbAccount.getCachedChildren(context); + for (const db of dbs) { + if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { + return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); + } + if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { + const fullConnectionString = await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); + } + } + + // We found the right account - just not the db. In this case we can still 'reveal' the account + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); + } else { + return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); + } + + } + + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = await dbAccount.getFullConnectionString(); + return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); + } else { + return new DatabaseAccountTreeItemInternal(expected, dbAccount); + } + + } + } + } catch (error) { + // Swallow all errors to avoid blocking the db account search + // https://github.com/microsoft/vscode-cosmosdb/issues/966 + } + + return undefined; } diff --git a/Source/commands/api/pickTreeItem.ts b/Source/commands/api/pickTreeItem.ts index f67ab039d..dc84ce55a 100644 --- a/Source/commands/api/pickTreeItem.ts +++ b/Source/commands/api/pickTreeItem.ts @@ -3,146 +3,98 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { PickAppResourceOptions } from "@microsoft/vscode-azext-utils/hostapi"; -import { databaseAccountType } from "../../constants"; -import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBDatabaseTreeItem } from "../../docdb/tree/DocDBDatabaseTreeItem"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { ext } from "../../extensionVariables"; -import { GraphDatabaseTreeItem } from "../../graph/tree/GraphDatabaseTreeItem"; -import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; -import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; -import { ParsedConnectionString } from "../../ParsedConnectionString"; -import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; -import { localize } from "../../utils/localize"; -import { - AzureDatabasesApiType, - DatabaseAccountTreeItem, - DatabaseTreeItem, - PickTreeItemOptions, -} from "../../vscode-cosmosdb.api"; -import { cacheTreeItem } from "./apiCache"; -import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; +import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; +import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; +import { databaseAccountType } from '../../constants'; +import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { ext } from '../../extensionVariables'; +import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; +import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; +import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; +import { ParsedConnectionString } from '../../ParsedConnectionString'; +import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; +import { localize } from '../../utils/localize'; +import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; +import { cacheTreeItem } from './apiCache'; +import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; -const databaseContextValues = [ - MongoDatabaseTreeItem.contextValue, - DocDBDatabaseTreeItem.contextValue, - GraphDatabaseTreeItem.contextValue, - PostgresDatabaseTreeItem.contextValue, -]; +const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case "Mongo": - return MongoDatabaseTreeItem.contextValue; - case "SQL": - return DocDBDatabaseTreeItem.contextValue; - case "Graph": - return GraphDatabaseTreeItem.contextValue; - case "Postgres": - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } + switch (apiType) { + case 'Mongo': + return MongoDatabaseTreeItem.contextValue; + case 'SQL': + return DocDBDatabaseTreeItem.contextValue; + case 'Graph': + return GraphDatabaseTreeItem.contextValue; + case 'Postgres': + return PostgresDatabaseTreeItem.contextValue; + default: + throw new RangeError(`Unsupported api type "${apiType}".`); + } } -export async function pickTreeItem( - pickTreeOptions: PickTreeItemOptions -): Promise { - return await callWithTelemetryAndErrorHandling( - "api.pickTreeItem", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case "Database": - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType - ? pickTreeOptions.apiType.map(getDatabaseContextValue) - : databaseContextValues; - break; - case "DatabaseAccount": - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError( - `Unsupported resource type "${pickTreeOptions.resourceType}".` - ); - } +export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { + return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const pickedItem = await ext.rgApi.pickAppResource( - context, - options - ); + const options: PickAppResourceOptions = {}; + switch (pickTreeOptions.resourceType) { + case 'Database': + options.filter = { type: databaseAccountType }; + options.expectedChildContextValue = pickTreeOptions.apiType ? + pickTreeOptions.apiType.map(getDatabaseContextValue) : + databaseContextValues; + break; + case 'DatabaseAccount': + options.filter = { type: databaseAccountType }; + break; + default: + throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); + } - let parsedCS: ParsedConnectionString; - let accountNode: - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem; - let databaseNode: - | MongoDatabaseTreeItem - | DocDBDatabaseTreeItemBase - | PostgresDatabaseTreeItem - | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString( - pickedItem.connectionString - ); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError( - localize( - "invalidItem", - 'Invalid item "{0}".', - pickedItem.constructor.name - ) - ); - } + const pickedItem = await ext.rgApi.pickAppResource(context, options); - const result = databaseNode - ? new DatabaseTreeItemInternal( - parsedCS, - databaseNode.databaseName, - accountNode, - databaseNode - ) - : new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - } - ); + let parsedCS: ParsedConnectionString; + let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; + let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; + if (pickedItem instanceof MongoAccountTreeItem) { + parsedCS = await parseMongoConnectionString(pickedItem.connectionString); + accountNode = pickedItem; + } else if (pickedItem instanceof DocDBAccountTreeItemBase) { + parsedCS = parseDocDBConnectionString(pickedItem.connectionString); + accountNode = pickedItem; + } else if (pickedItem instanceof PostgresServerTreeItem) { + parsedCS = await pickedItem.getFullConnectionString(); + accountNode = pickedItem; + } else if (pickedItem instanceof MongoDatabaseTreeItem) { + parsedCS = await parseMongoConnectionString(pickedItem.connectionString); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { + parsedCS = parseDocDBConnectionString(pickedItem.connectionString); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof PostgresDatabaseTreeItem) { + parsedCS = await pickedItem.parent.getFullConnectionString(); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else { + throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); + } + + const result = databaseNode ? + new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : + new DatabaseAccountTreeItemInternal(parsedCS, accountNode); + cacheTreeItem(parsedCS, result); + return result; + }); } diff --git a/Source/commands/api/revealTreeItem.ts b/Source/commands/api/revealTreeItem.ts index 185ff340c..d13589351 100644 --- a/Source/commands/api/revealTreeItem.ts +++ b/Source/commands/api/revealTreeItem.ts @@ -3,29 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; import { ext } from "../../extensionVariables"; export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling( - "api.revealTreeItem", - async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem(resourceId, { - ...context, - loadAll: true, - }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { - select: true, - focus: true, - expand: true, - }); - } - } - ); + return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { + const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); + if (node) { + await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); + } + }); } diff --git a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts index d409dcc0a..1ef9ca645 100644 --- a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts @@ -7,13 +7,13 @@ import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } + public async execute(context: IDeleteWizardContext): Promise { + await context.node.deleteTreeItem(context); + } - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } + public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { + return true; + } } diff --git a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts index e20bafa90..762beb96e 100644 --- a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts @@ -1,20 +1,13 @@ /*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - ExecuteActivityContext, - IActionContext, - ISubscriptionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; -export interface IDeleteWizardContext - extends IActionContext, - ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; +export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { + node: AzExtTreeItem; + deletePostgres: boolean; + resourceGroupToDelete?: string; + subscription: ISubscriptionContext; } diff --git a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts index b862cb33e..a90956b30 100644 --- a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts @@ -3,49 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { ext } from "../../extensionVariables"; -import { createCosmosDBClient } from "../../utils/azureClients"; -import { getDatabaseAccountNameFromId } from "../../utils/azureUtils"; -import { localize } from "../../utils/localize"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; +import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { ext } from '../../extensionVariables'; +import { createCosmosDBClient } from '../../utils/azureClients'; +import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; +import { localize } from '../../utils/localize'; +import { IDeleteWizardContext } from './IDeleteWizardContext'; -export async function deleteCosmosDBAccount( - context: IDeleteWizardContext, - node: AzExtTreeItem -): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([ - context, - node.subscription, - ]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait( - resourceGroup, - accountName - ); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: deletingMessage, - }, - async () => { - await deletePromise; - const deleteMessage: string = localize( - "deleteAccountMsg", - `Successfully deleted account "{0}".`, - accountName - ); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - } - ); - } else { - await deletePromise; - } +export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { + const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); + const resourceGroup: string = getResourceGroupFromId(node.fullId); + const accountName: string = getDatabaseAccountNameFromId(node.fullId); + const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); + if (!context.suppressNotification) { + const deletingMessage: string = `Deleting account "${accountName}"...`; + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { + await deletePromise; + const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + }); + } else { + await deletePromise; + } } diff --git a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts index ac6857848..4792710d4 100644 --- a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts @@ -3,51 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - AzureWizard, - DeleteConfirmationStep, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; import { createActivityContext } from "../../utils/activityUtils"; import { localize } from "../../utils/localize"; import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; -export async function deleteDatabaseAccount( - context: IActionContext, - node: AzExtTreeItem, - isPostgres: boolean = false -): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()), - }); - const title = wizardContext.deletePostgres - ? localize("deletePoSer", 'Delete Postgres Server "{0}"', node.label) - : localize("deleteDbAcc", 'Delete Database Account "{0}"', node.label); +export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { + const wizardContext: IDeleteWizardContext = Object.assign(context, { + node, + deletePostgres: isPostgres, + subscription: node.subscription, + ...(await createActivityContext()) + }); - const confirmationMessage = wizardContext.deletePostgres - ? localize( - "deleteAccountConfirm", - 'Are you sure you want to delete server "{0}" and its contents?', - node.label - ) - : localize( - "deleteAccountConfirm", - 'Are you sure you want to delete account "{0}" and its contents?', - node.label - ); + const title = wizardContext.deletePostgres ? + localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : + localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()], - }); + const confirmationMessage = wizardContext.deletePostgres ? + localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : + localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); - await wizard.prompt(); - await wizard.execute(); + const wizard = new AzureWizard(wizardContext, { + title, + promptSteps: [new DeleteConfirmationStep(confirmationMessage)], + executeSteps: [new DatabaseAccountDeleteStep()] + }); + + await wizard.prompt(); + await wizard.execute(); } diff --git a/Source/commands/importDocuments.ts b/Source/commands/importDocuments.ts index 305af31eb..bd4c83e3f 100644 --- a/Source/commands/importDocuments.ts +++ b/Source/commands/importDocuments.ts @@ -3,209 +3,161 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from "@azure/cosmos"; -import { IActionContext, parseError } from "@microsoft/vscode-azext-utils"; -import * as fse from "fs-extra"; -import * as vscode from "vscode"; -import { cosmosMongoFilter, sqlFilter } from "../constants"; -import { DocDBCollectionTreeItem } from "../docdb/tree/DocDBCollectionTreeItem"; -import { ext } from "../extensionVariables"; -import { MongoCollectionTreeItem } from "../mongo/tree/MongoCollectionTreeItem"; -import { nonNullProp, nonNullValue } from "../utils/nonNull"; -import { getRootPath } from "../utils/workspacUtils"; +import { ItemDefinition } from '@azure/cosmos'; +import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import * as vscode from 'vscode'; +import { cosmosMongoFilter, sqlFilter } from '../constants'; +import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; +import { ext } from '../extensionVariables'; +import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; +import { nonNullProp, nonNullValue } from '../utils/nonNull'; +import { getRootPath } from '../utils/workspacUtils'; -export async function importDocuments( - context: IActionContext, - uris: vscode.Uri[] | undefined, - collectionNode: - | MongoCollectionTreeItem - | DocDBCollectionTreeItem - | undefined -): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith(".json")) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog( - `Ignoring the following files which are not json:` - ); - ignoredUris.forEach((uri) => - ext.outputChannel.appendLine(`${uri.fsPath}`) - ); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource< - MongoCollectionTreeItem | DocDBCollectionTreeItem - >(context, { - filter: [cosmosMongoFilter, sqlFilter], - expectedChildContextValue: [ - MongoCollectionTreeItem.contextValue, - DocDBCollectionTreeItem.contextValue, - ], - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents...", - }, - async (progress) => { - uris = nonNullValue(uris, "uris"); - collectionNode = nonNullValue(collectionNode, "collectionNode"); +export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { + if (!uris) { + uris = await askForDocuments(context); + } + const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 + uris = uris.filter((uri) => { + if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { + return true; + } else { + ignoredUris.push(uri); + return false; + } + }); + if (ignoredUris.length) { + ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); + ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); + ext.outputChannel.show(); + } + if (!collectionNode) { + collectionNode = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + sqlFilter + ], + expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] + }); + } + let result: string; + result = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Importing documents..." + }, + async (progress) => { + uris = nonNullValue(uris, 'uris'); + collectionNode = nonNullValue(collectionNode, 'collectionNode'); - progress.report({ - increment: 20, - message: "Parsing documents for errors", - }); - const documents = await parseDocuments(uris); - progress.report({ - increment: 30, - message: "Parsed documents. Importing", - }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo( - collectionNode, - documents - ); - } else { - result = await insertDocumentsIntoDocdb( - collectionNode, - documents, - uris - ); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); + progress.report({ increment: 20, message: "Parsing documents for errors" }); + const documents = await parseDocuments(uris); + progress.report({ increment: 30, message: "Parsed documents. Importing" }); + if (collectionNode instanceof MongoCollectionTreeItem) { + result = await insertDocumentsIntoMongo(collectionNode, documents); + } else { + result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); + } + progress.report({ increment: 50, message: "Finished importing" }); + return result; + } + ); - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); + await collectionNode.refresh(context); + await vscode.window.showInformationMessage(result); } async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"], - }, - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); + const openDialogOptions: vscode.OpenDialogOptions = { + canSelectMany: true, + openLabel: "Import", + filters: { + JSON: ["json"] + } + }; + const rootPath: string | undefined = getRootPath(); + if (rootPath) { + openDialogOptions.defaultUri = vscode.Uri.file(rootPath); + } + return await context.ui.showOpenDialog(openDialogOptions); } // eslint-disable-next-line @typescript-eslint/no-explicit-any async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog( - "Errors found in documents listed below. Please fix these." - ); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error( - `Errors found in some documents. Please see the output, fix these and try again.` - ); - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let documents: any[] = []; + let errorFoundFlag: boolean = false; + for (const uri of uris) { + let parsed; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + parsed = await fse.readJSON(uri.fsPath); + } catch (e) { + if (!errorFoundFlag) { + errorFoundFlag = true; + ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); + ext.outputChannel.show(); + } + const err = parseError(e); + ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); + } + if (parsed) { + if (Array.isArray(parsed)) { + documents = documents.concat(parsed); + } else { + documents.push(parsed); + } + } + } + if (errorFoundFlag) { + throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); + } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return documents; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb( - collectionNode: DocDBCollectionTreeItem, - documents: any[], - uris: vscode.Uri[] -): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if ( - !collectionNode.documentsTreeItem.documentHasPartitionKey(document) - ) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog( - `The following documents do not contain the required partition key:` - ); - erroneousFiles.forEach((file) => - ext.outputChannel.appendLine(file.path) - ); - ext.outputChannel.show(); - throw new Error( - `See output for list of documents that do not contain the partition key '${ - nonNullProp(collectionNode, "partitionKey").paths[0] - }' required by collection '${collectionNode.label}'` - ); - } - for (const document of documents) { - const retrieved: ItemDefinition = - await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; +async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { + const ids: string[] = []; + let i = 0; + const erroneousFiles: vscode.Uri[] = []; + for (i = 0; i < documents.length; i++) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const document: ItemDefinition = documents[i]; + if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { + erroneousFiles.push(uris[i]); + } + } + if (erroneousFiles.length) { + ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); + erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); + ext.outputChannel.show(); + throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); + } + for (const document of documents) { + const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); + if (retrieved.id) { + ids.push(retrieved.id); + } + } + const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; + for (const id of ids) { + ext.outputChannel.appendLine(`Inserted document: ${id}`); + } + return result; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo( - node: MongoCollectionTreeItem, - documents: any[] -): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; +async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { + let output = ""; + const parsed = await node.collection.insertMany(documents); + if (parsed.result && parsed.result.ok) { + output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; + for (const inserted of Object.values(parsed.insertedIds)) { + ext.outputChannel.appendLine(`Inserted document: ${inserted}`); + } + } + return output; } diff --git a/Source/constants.ts b/Source/constants.ts index 4d43ec018..0e6a4a14e 100644 --- a/Source/constants.ts +++ b/Source/constants.ts @@ -5,62 +5,47 @@ export const isWindows: boolean = /^win/.test(process.platform); -import * as assert from "assert"; -import * as fs from "fs"; -import * as path from "path"; -import { - CoreExperience, - GremlinExperience, - MongoExperience, - TableExperience, -} from "./AzureDBExperiences"; -import { ext } from "./extensionVariables"; +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as path from 'path'; +import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; +import { ext } from './extensionVariables'; export namespace Links { - export const LocalConnectionDebuggingTips: string = - "https://aka.ms/AA5zah5"; + export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; } export interface IThemedIconPath { - light: string; - dark: string; + light: string; + dark: string; } export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), "icons", "light", iconName), - dark: path.join(getResourcesPath(), "icons", "dark", iconName), - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), 'icons', 'light', iconName), + dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) + }; + assert(fs.existsSync(a.light)); + return a; } export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join( - getResourcesPath(), - "icons", - "theme-agnostic", - iconName - ), - dark: path.join( - getResourcesPath(), - "icons", - "theme-agnostic", - iconName - ), - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), + dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) + }; + assert(fs.existsSync(a.light)); + return a; } export function getResourcesPath(): string { - return ext.context.asAbsolutePath("resources"); + return ext.context.asAbsolutePath('resources'); } export const doubleClickDebounceDelay = 500; //milliseconds -export const defaultStoredProcedure = `function sample(prefix) { +export const defaultStoredProcedure = + `function sample(prefix) { var collection = getContext().getCollection(); // Query documents and take 1st item. @@ -85,69 +70,67 @@ export const defaultStoredProcedure = `function sample(prefix) { }); if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};`; +};` ; -export const emulatorPassword = - "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; +export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; // https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = "test"; +export const testDb: string = 'test'; -export const connectedPostgresKey: string = - "ms-azuretools.vscode-azuredatabases.connectedPostgresDB"; -export const postgresLanguageId: string = "postgres"; +export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; +export const postgresLanguageId: string = 'postgres'; export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = "query"; -export const postgresDefaultPort = "5432"; -export const postgresDefaultDatabase = "postgres"; -export const SERVERLESS_CAPABILITY_NAME = "EnableServerless"; +export const postgresBaseFileName: string = 'query'; +export const postgresDefaultPort = '5432'; +export const postgresDefaultDatabase = 'postgres'; +export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; -export const databaseAccountType = "Microsoft.DocumentDB/databaseAccounts"; +export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag, - }, + type: databaseAccountType, + kind: MongoExperience.kind, + tags: { + defaultExperience: mongoDefaultExperienceTag + } }; -export const gremlinDefaultExperienceTag = "Gremlin (graph)"; +export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag, - }, + type: databaseAccountType, + kind: GremlinExperience.kind, + tags: { + defaultExperience: gremlinDefaultExperienceTag + } }; -export const tableDefaultExperienceTag = "Azure Table"; +export const tableDefaultExperienceTag = 'Azure Table'; export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag, - }, + type: databaseAccountType, + kind: TableExperience.kind, + tags: { + defaultExperience: tableDefaultExperienceTag + } }; -export const sqlDefaultExperienceTag = "Core (SQL)"; +export const sqlDefaultExperienceTag = 'Core (SQL)'; export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag, - }, + type: databaseAccountType, + kind: CoreExperience.kind, + tags: { + defaultExperience: sqlDefaultExperienceTag + } }; export const postgresFlexibleFilter = { - type: "Microsoft.DBforPostgreSQL/flexibleServers", + type: 'Microsoft.DBforPostgreSQL/flexibleServers' }; export const postgresSingleFilter = { - type: "Microsoft.DBForPostgreSQL/servers", + type: 'Microsoft.DBForPostgreSQL/servers' }; diff --git a/Source/docdb/docDBConnectionStrings.ts b/Source/docdb/docDBConnectionStrings.ts index 3389eeea4..946490d21 100644 --- a/Source/docdb/docDBConnectionStrings.ts +++ b/Source/docdb/docDBConnectionStrings.ts @@ -3,64 +3,40 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as url from "url"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullProp } from "../utils/nonNull"; +import * as url from 'url'; +import { ParsedConnectionString } from '../ParsedConnectionString'; +import { nonNullProp } from '../utils/nonNull'; -export function parseDocDBConnectionString( - connectionString: string -): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString( - connectionString, - "AccountEndpoint" - ); - const masterKey = getPropertyFromConnectionString( - connectionString, - "AccountKey" - ); - const databaseName = getPropertyFromConnectionString( - connectionString, - "Database" - ); - if (!endpoint || !masterKey) { - throw new Error("Invalid Document DB connection string."); - } - return new ParsedDocDBConnectionString( - connectionString, - endpoint, - masterKey, - databaseName - ); +export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { + const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); + const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); + const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); + if (!endpoint || !masterKey) { + throw new Error('Invalid Document DB connection string.'); + } + return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); } -function getPropertyFromConnectionString( - connectionString: string, - property: string -): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, "i"); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; +function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { + const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); + const match = connectionString.match(regexp); + return match ? match[1] : undefined; } export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - public readonly documentEndpoint: string; - public readonly masterKey: string; + public readonly documentEndpoint: string; + public readonly masterKey: string; - constructor( - connectionString: string, - endpoint: string, - masterKey: string, - databaseName: string | undefined - ) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; + constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { + super(connectionString, databaseName); + this.documentEndpoint = endpoint; + this.masterKey = masterKey; - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, "hostname"); - this.port = nonNullProp(parsedEndpoint, "port"); - } + const parsedEndpoint = url.parse(endpoint); + this.hostName = nonNullProp(parsedEndpoint, 'hostname'); + this.port = nonNullProp(parsedEndpoint, 'port'); + } } diff --git a/Source/docdb/getCosmosClient.ts b/Source/docdb/getCosmosClient.ts index f422ec3c2..3b285fc9c 100644 --- a/Source/docdb/getCosmosClient.ts +++ b/Source/docdb/getCosmosClient.ts @@ -6,33 +6,14 @@ import { CosmosClient } from "@azure/cosmos"; import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; import * as https from "https"; -import * as vscode from "vscode"; +import * as vscode from 'vscode'; import { ext } from "../extensionVariables"; -export function getCosmosClient( - endpoint: string, - key: string, - isEmulator: boolean | undefined -): CosmosClient { - const vscodeStrictSSL: boolean | undefined = vscode.workspace - .getConfiguration() - .get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace - .getConfiguration() - .get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { - enableEndpointDiscovery: - enableEndpointDiscovery === undefined - ? true - : enableEndpointDiscovery, - }; - return new CosmosClient({ - endpoint, - key, - userAgentSuffix: appendExtensionUserAgent(), - agent: new https.Agent({ - rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL, - }), - connectionPolicy: connectionPolicy, - }); +export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { + + const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); + const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); + const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; + return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); + } diff --git a/Source/docdb/registerDocDBCommands.ts b/Source/docdb/registerDocDBCommands.ts index a8f29c69d..5eb7545e4 100644 --- a/Source/docdb/registerDocDBCommands.ts +++ b/Source/docdb/registerDocDBCommands.ts @@ -3,12 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - IActionContext, - ITreeItemPickerContext, - registerCommandWithTreeNodeUnwrapping, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; import { commands } from "vscode"; import { doubleClickDebounceDelay, sqlFilter } from "../constants"; import { ext } from "../extensionVariables"; @@ -21,170 +16,89 @@ import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeI import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBDatabase", - createDocDBDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBCollection", - createDocDBCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBDocument", - async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDocumentsTreeItem.contextValue - ); - } - const documentNode = ( - await node.createChild(context) - ); - await commands.executeCommand( - "cosmosDB.openDocument", - documentNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createDocDBStoredProcedure", - async ( - context: IActionContext, - node?: DocDBStoredProceduresTreeItem - ) => { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBStoredProceduresTreeItem.contextValue - ); - } - const childNode = await node.createChild(context); - await commands.executeCommand( - "cosmosDB.openStoredProcedure", - childNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBDatabase", - deleteDocDBDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBCollection", - deleteDocDBCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openStoredProcedure", - async ( - context: IActionContext, - node?: DocDBStoredProcedureTreeItem - ) => { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBStoredProcedureTreeItem.contextValue - ); - } - await ext.fileSystem.showTextDocument(node); - }, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBDocument", - async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDocumentTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteDocDBStoredProcedure", - async ( - context: IActionContext, - node?: DocDBStoredProcedureTreeItem - ) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBStoredProcedureTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { + if (!node) { + node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); + } + const documentNode = await node.createChild(context); + await commands.executeCommand("cosmosDB.openDocument", documentNode); + + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { + if (!node) { + node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); + } + const childNode = await node.createChild(context); + await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); + + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { + if (!node) { + node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); + } + await ext.fileSystem.showTextDocument(node); + }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); + + } + await node.deleteTreeItem(context); + }); } -export async function createDocDBDatabase( - context: IActionContext, - node?: DocDBAccountTreeItem -): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = ( - await node.createChild(context) - ); - await databaseNode.createChild(context); +export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { + if (!node) { + node = await pickDocDBAccount(context); + } + const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); + await databaseNode.createChild(context); } -export async function createDocDBCollection( - context: IActionContext, - node?: DocDBDatabaseTreeItem -): Promise { - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDatabaseTreeItem.contextValue - ); - } - await node.createChild(context); +export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { + if (!node) { + node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); + } + await node.createChild(context); } -export async function deleteDocDBDatabase( - context: IActionContext, - node?: DocDBDatabaseTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBDatabaseTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); +export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); + } + await node.deleteTreeItem(context); } -export async function deleteDocDBCollection( - context: IActionContext, - node?: DocDBCollectionTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount( - context, - DocDBCollectionTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); +export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); + } + await node.deleteTreeItem(context); } -async function pickDocDBAccount( - context: IActionContext, - expectedContextValue?: string | RegExp | (string | RegExp)[] -): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [sqlFilter], - expectedChildContextValue: expectedContextValue, - }); +async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [ + sqlFilter + ], + expectedChildContextValue: expectedContextValue + }); } diff --git a/Source/docdb/tree/DocDBAccountTreeItem.ts b/Source/docdb/tree/DocDBAccountTreeItem.ts index 242af5546..0cee7ed06 100644 --- a/Source/docdb/tree/DocDBAccountTreeItem.ts +++ b/Source/docdb/tree/DocDBAccountTreeItem.ts @@ -3,37 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseDefinition, Resource } from "@azure/cosmos"; -import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { DatabaseDefinition, Resource } from '@azure/cosmos'; +import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; +import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; +import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; +import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBDocumentServer"; + public contextValue: string = DocDBAccountTreeItem.contextValue; - public initChild( - resource: DatabaseDefinition & Resource - ): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } + public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { + this.valuesToMask.push(resource._rid, resource._self); + return new DocDBDatabaseTreeItem(this, resource); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case DocDBDatabaseTreeItem.contextValue: + case DocDBCollectionTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case DocDBDocumentsTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/docdb/tree/DocDBAccountTreeItemBase.ts b/Source/docdb/tree/DocDBAccountTreeItemBase.ts index 2984b29ef..da9eec6b7 100644 --- a/Source/docdb/tree/DocDBAccountTreeItemBase.ts +++ b/Source/docdb/tree/DocDBAccountTreeItemBase.ts @@ -3,139 +3,93 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { - CosmosClient, - DatabaseDefinition, - DatabaseResponse, - FeedOptions, - QueryIterator, - Resource, -} from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - ICreateChildImplContext, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; -import { - SERVERLESS_CAPABILITY_NAME, - getThemeAgnosticIconPath, -} from "../../constants"; -import { nonNullProp } from "../../utils/nonNull"; -import { rejectOnTimeout } from "../../utils/timeout"; -import { getCosmosClient } from "../getCosmosClient"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; +import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; +import { nonNullProp } from '../../utils/nonNull'; +import { rejectOnTimeout } from '../../utils/timeout'; +import { getCosmosClient } from '../getCosmosClient'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; /** * This class provides common logic for DocumentDB, Graph, and Table accounts * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase< - DatabaseDefinition & Resource -> { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; +export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { + public readonly label: string; + public readonly childTypeLabel: string = "Database"; - constructor( - parent: AzExtParentTreeItem, - id: string, - label: string, - endpoint: string, - masterKey: string, - isEmulator: boolean | undefined, - readonly databaseAccount?: DatabaseAccountGetResults - ) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => - getCosmosClient(endpoint, masterKey, isEmulator), - }; - this.valuesToMask.push(id, endpoint, masterKey); - } + constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { + super(parent); + this.id = id; + this.label = label; + this.root = { + endpoint, + masterKey, + isEmulator, + getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) + }; - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } + this.valuesToMask.push(id, endpoint, masterKey); + } - public get iconPath(): - | string - | vscode.Uri - | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath("CosmosDBAccount.svg"); - } + public get connectionString(): string { + return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; + } - public get isServerless(): boolean { - return this.databaseAccount?.capabilities - ? this.databaseAccount.capabilities.some( - (cap) => cap.name === SERVERLESS_CAPABILITY_NAME - ) - : false; - } + public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath('CosmosDBAccount.svg'); + } - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return client.databases.readAll(feedOptions); - } + public get isServerless(): boolean { + return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - validateInput: validateDatabaseName, - stepName: "createDatabase", - }); + } - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ - id: databaseName, - }); - return this.initChild(nonNullProp(database, "resource")); - } + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return client.databases.readAll(feedOptions); + } - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = - "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout( - 2000, - () => super.loadMoreChildrenImpl(clearCache), - unableToReachEmulatorMessage - ); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } + public async createChildImpl(context: ICreateChildImplContext): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: 'Database Name', + validateInput: validateDatabaseName, + stepName: 'createDatabase' + }); - public async deleteTreeItemImpl( - context: IDeleteWizardContext - ): Promise { - await deleteCosmosDBAccount(context, this); - } + const client = this.root.getCosmosClient(); + const database: DatabaseResponse = await client.databases.create({ id: databaseName }); + return this.initChild(nonNullProp(database, 'resource')); + } + + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (this.root.isEmulator) { + const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; + return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); + } else { + return await super.loadMoreChildrenImpl(clearCache); + } + } + + public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { + await deleteCosmosDBAccount(context, this); + } } function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; + if (!name || name.length < 1 || name.length > 255) { + return "Name has to be between 1 and 255 chars long"; + } + if (name.endsWith(" ")) { + return "Database name cannot end with space"; + } + if (/[/\\?#=]/.test(name)) { + return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBCollectionTreeItem.ts b/Source/docdb/tree/DocDBCollectionTreeItem.ts index 8849bee34..987bbe3b4 100644 --- a/Source/docdb/tree/DocDBCollectionTreeItem.ts +++ b/Source/docdb/tree/DocDBCollectionTreeItem.ts @@ -3,115 +3,90 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - ContainerDefinition, - CosmosClient, - PartitionKeyDefinition, - Resource, -} from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; +import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; +import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; +import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; +import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; /** * Represents a DocumentDB collection */ export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor( - parent: DocDBDatabaseTreeItem, - private _container: ContainerDefinition & Resource - ) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( - this - ); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteCollection" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl( - expectedContextValues: (string | RegExp)[] - ): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getDatabaseClient(client).container(this.id); - } + public static contextValue: string = "cosmosDBDocumentCollection"; + public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; + public readonly documentsTreeItem: DocDBDocumentsTreeItem; + public readonly parent: DocDBDatabaseTreeItem; + + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { + super(parent); + this.parent = parent; + this.documentsTreeItem = new DocDBDocumentsTreeItem(this); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._container.id; + } + + public get label(): string { + return this._container.id; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public get link(): string { + return this._container._self; + } + + public get partitionKey(): PartitionKeyDefinition | undefined { + return this._container.partitionKey; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + return [this.documentsTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case DocDBDocumentsTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + return this.documentsTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return (this.parent.getDatabaseClient(client)).container(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItem.ts b/Source/docdb/tree/DocDBDatabaseTreeItem.ts index b51504cc2..ee8c23694 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItem.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItem.ts @@ -3,27 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ContainerDefinition, - CosmosClient, - Database, - Resource, -} from "@azure/cosmos"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItemBase } from "./DocDBDatabaseTreeItemBase"; +import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; + public static contextValue: string = "cosmosDBDocumentDatabase"; + public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = 'Collection'; - public initChild( - container: ContainerDefinition & Resource - ): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } + public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { + return new DocDBCollectionTreeItem(this, container); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts index 15a935e5c..aa7e8d779 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts @@ -3,27 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ContainerDefinition, - ContainerResponse, - CosmosClient, - DatabaseDefinition, - FeedOptions, - QueryIterator, - RequestOptions, - Resource, -} from "@azure/cosmos"; -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; +import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; const minThroughputFixed: number = 400; const minThroughputPartitioned: number = 400; @@ -34,177 +19,143 @@ const throughputStepSize = 100; * This class provides common logic for DocumentDB, Graph, and Table databases * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase< - ContainerDefinition & Resource -> { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor( - parent: DocDBAccountTreeItemBase, - database: DatabaseDefinition & Resource - ) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("database"); - } - - public get id(): string { - return nonNullProp(this._database, "id"); - } - - public get label(): string { - return nonNullProp(this._database, "id"); - } - - public get link(): string { - return nonNullProp(this._database, "_self"); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return client - .database(this._database.id) - .containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteDatabase" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}`, - }); - - const containerDefinition: ContainerDefinition = { - id: containerName, - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey], - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !containerDefinition.partitionKey; - const minThroughput = isFixed - ? minThroughputFixed - : minThroughputPartitioned; - const throughput: number = Number( - await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: "throughputCapacity", - validateInput: (input: string) => - validateThroughput(isFixed, input), - }) - ); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client - .database(this.id) - .containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, "resource")); - } - - protected async getNewPartitionKey( - context: IActionContext - ): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: "Enter the partition key for the collection, or leave blank for fixed size.", - stepName: "partitionKeyForCollection", - validateInput: this.validatePartitionKey, - placeHolder: "e.g. /address/zipCode", - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { - partitionKey = "/" + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } +export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { + public readonly parent: DocDBAccountTreeItemBase; + private readonly _database: DatabaseDefinition & Resource; + + constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { + super(parent); + this._database = database; + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('database'); + } + + public get id(): string { + return nonNullProp(this._database, 'id'); + } + + public get label(): string { + return nonNullProp(this._database, 'id'); + } + + public get link(): string { + return nonNullProp(this._database, '_self'); + } + + public get connectionString(): string { + return this.parent.connectionString.concat(`;Database=${this.id}`); + } + + public get databaseName(): string { + return this._database.id; + } + + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return client.database(this._database.id).containers.readAll(feedOptions); + } + + // Delete the database + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await client.database(this.id).delete(); + } + + // Create a DB collection + public async createChildImpl(context: ICreateChildImplContext): Promise { + const containerName = await context.ui.showInputBox({ + placeHolder: `Enter an id for your ${this.childTypeLabel}`, + validateInput: validateCollectionName, + stepName: `create${this.childTypeLabel}` + }); + + const containerDefinition: ContainerDefinition = { + id: containerName + }; + + const partitionKey = await this.getNewPartitionKey(context); + if (partitionKey) { + containerDefinition.partitionKey = { + paths: [partitionKey] + }; + } + const options: RequestOptions = {}; + + if (!this.parent.isServerless) { + const isFixed: boolean = !(containerDefinition.partitionKey); + const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; + const throughput: number = Number(await context.ui.showInputBox({ + value: minThroughput.toString(), + prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, + stepName: 'throughputCapacity', + validateInput: (input: string) => validateThroughput(isFixed, input) + })); + + if (throughput !== 0) { + options.offerThroughput = throughput; + } + } + + context.showCreatingTreeItem(containerName); + const client = this.root.getCosmosClient(); + const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); + + return this.initChild(nonNullProp(container, 'resource')); + } + + protected async getNewPartitionKey(context: IActionContext): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', + stepName: 'partitionKeyForCollection', + validateInput: this.validatePartitionKey, + placeHolder: 'e.g. /address/zipCode' + }); + + if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { + partitionKey = '/' + partitionKey; + } + + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + return undefined; + } } -function validateThroughput( - isFixed: boolean, - input: string -): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed - ? minThroughputFixed - : minThroughputPartitioned; - const value = Number(input); - if ( - value < minThroughput || - value > maxThroughput || - (value - minThroughput) % throughputStepSize !== 0 - ) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; +function validateThroughput(isFixed: boolean, input: string): string | undefined | null { + if (input === "0") { + return undefined; + } + + try { + const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; + const value = Number(input); + if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { + return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; + } + } catch (err) { + return "Input must be a number"; + } + return undefined; } function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; + if (!name) { + return "Collection name cannot be empty"; + } + if (name.endsWith(" ")) { + return "Collection name cannot end with space"; + } + if (/[/\\?#]/.test(name)) { + return `Collection name cannot contain the characters '\\', '/', '#', '?'`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBDocumentTreeItem.ts b/Source/docdb/tree/DocDBDocumentTreeItem.ts index 408dedfd7..1505572d9 100644 --- a/Source/docdb/tree/DocDBDocumentTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentTreeItem.ts @@ -3,171 +3,131 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - CosmosClient, - Item, - ItemDefinition, - RequestOptions, -} from "@azure/cosmos"; -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { nonNullProp } from "../../utils/nonNull"; -import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; -import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; -import { sanitizeId } from "./DocDBUtils"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; - -const hiddenFields: string[] = [ - "_rid", - "_self", - "_etag", - "_attachments", - "_ts", -]; +import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; +import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { nonNullProp } from '../../utils/nonNull'; +import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; +import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; +import { sanitizeId } from './DocDBUtils'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; + +const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; /** * Represents a Cosmos DB DocumentDB (SQL) document */ -export class DocDBDocumentTreeItem - extends AzExtTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = "cosmosDB.openDocument"; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + "-cosmos-document.json"; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("file"); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteDocument" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent( - _context: IActionContext, - content: string - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error( - `The "_self" and "_etag" fields are required to update a document` - ); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { - accessCondition: { type: "IfMatch", condition: newData._etag }, - }; - const response = await this.getDocumentClient(client).replace( - newData, - options - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { - //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split("/"); - if (fields[0] === "") { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { - //Partition Key exists, but this document doesn't have a value - return ""; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent - .getContainerClient(client) - .item( - nonNullProp(this.document, "id"), - this.getPartitionKeyValue() - ); - } +export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { + public static contextValue: string = "cosmosDBDocument"; + public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; + public readonly parent: DocDBDocumentsTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + private _label: string; + private _document: ItemDefinition; + + constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { + super(parent); + this._document = document; + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + this.commandId = 'cosmosDB.openDocument'; + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); + } + + public get filePath(): string { + return this.label + '-cosmos-document.json'; + } + + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + } + + public get link(): string { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return this.document._self; + } + + get document(): ItemDefinition { + return this._document; + } + + get label(): string { + return this._label; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('file'); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.getDocumentClient(client).delete(); + } + + public async getFileContent(): Promise { + const clonedDoc: {} = { ...this.document }; + for (const field of hiddenFields) { + delete clonedDoc[field]; + } + return JSON.stringify(clonedDoc, null, 2); + } + + public async writeFileContent(_context: IActionContext, content: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const newData = JSON.parse(content); + for (const field of hiddenFields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + newData[field] = this.document[field]; + } + + const client: CosmosClient = this.root.getCosmosClient(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (["_etag"].some((element) => !newData[element])) { + throw new Error(`The "_self" and "_etag" fields are required to update a document`); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; + const response = await this.getDocumentClient(client).replace(newData, options); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this._document = response.resource; + } + } + + private getPartitionKeyValue(): string | undefined | Object { + const partitionKey = this.parent.parent.partitionKey; + if (!partitionKey) { //Fixed collections -> no partitionKeyValue + return undefined; + } + const fields = partitionKey.paths[0].split('/'); + if (fields[0] === '') { + fields.shift(); + } + let value; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + value = value ? value[field] : this.document[field]; + if (!value) { //Partition Key exists, but this document doesn't have a value + return ''; + } + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + } + + private getDocumentClient(client: CosmosClient): Item { + return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); + } } diff --git a/Source/docdb/tree/DocDBDocumentsTreeItem.ts b/Source/docdb/tree/DocDBDocumentsTreeItem.ts index ec05451e0..b8265444d 100644 --- a/Source/docdb/tree/DocDBDocumentsTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentsTreeItem.ts @@ -3,160 +3,127 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - CosmosClient, - FeedOptions, - ItemDefinition, - ItemResponse, - QueryIterator, -} from "@azure/cosmos"; -import { - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; +import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; /** * This class provides logic for DocumentDB collections */ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - let docID = await context.ui.showInputBox({ - prompt: "Enter a document ID or leave blank for a generated ID", - stepName: "createDocument", - }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = await this.promptForPartitionKey(context, body); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = - await this.getContainerClient( - this.root.getCosmosClient() - ).items.create(body); - return nonNullProp(item, "resource"); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = - this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === "/") { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split("/"); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey( - context: IActionContext, - body: ItemDefinition - ): Promise { - const partitionKey: string | undefined = - this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: "valueforParititionKey", - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign( - body, - this.createPartitionPathObject(partitionKey, partitionKeyValue) - ); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject( - partitionKey: string, - partitionKeyValue: string - ): Object { - //remove leading slash - if (partitionKey[0] === "/") { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split("/"); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } + public static contextValue: string = "cosmosDBDocumentsGroup"; + public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; + public readonly childTypeLabel: string = "Documents"; + public readonly parent: DocDBCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public get id(): string { + return "$Documents"; + } + + public get label(): string { + return "Documents"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return this.getContainerClient(client).items.readAll(feedOptions); + } + + public initChild(document: ItemDefinition): DocDBDocumentTreeItem { + return new DocDBDocumentTreeItem(this, document); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); + + docID = docID.trim(); + let body: ItemDefinition = { id: docID }; + body = (await this.promptForPartitionKey(context, body)); + context.showCreatingTreeItem(docID); + const item: ItemDefinition = await this.createDocument(body); + + return this.initChild(item); + } + + public async createDocument(body: ItemDefinition): Promise { + const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); + return nonNullProp(item, 'resource'); + } + + public documentHasPartitionKey(doc: Object): boolean { + let interim = doc; + let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (!partitionKey) { + return true; + } + if (partitionKey[0] === '/') { + partitionKey = partitionKey.slice(1); + } + const partitionKeyPath = partitionKey.split('/'); + + for (const prop of partitionKeyPath) { + // eslint-disable-next-line no-prototype-builtins + if (interim.hasOwnProperty(prop)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[prop]; + } else { + return false; + } + } + return true; + } + + public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { + const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (partitionKey) { + const partitionKeyValue: string = await context.ui.showInputBox({ + prompt: `Enter a value for the partition key ("${partitionKey}")`, + stepName: 'valueforParititionKey' + }); + // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. + // We need to present the partitionKey value as part of the document contents + Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); + } + return body; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + // Create a nested Object given the partition key path and value + private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { + //remove leading slash + if (partitionKey[0] === '/') { + partitionKey = partitionKey.slice(1); + } + const keyPath = partitionKey.split('/'); + const PartitionPath: Object = {}; + let interim: Object = PartitionPath; + let i: number; + for (i = 0; i < keyPath.length - 1; i++) { + interim[keyPath[i]] = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[keyPath[i]]; + } + interim[keyPath[i]] = partitionKeyValue; + return PartitionPath; + } } diff --git a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts index 20ced0d3e..899eccd27 100644 --- a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts @@ -3,100 +3,74 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; +import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; +import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; /** * Represents a Cosmos DB DocumentDB (SQL) stored procedure */ -export class DocDBStoredProcedureTreeItem - extends AzExtTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = - DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); +export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { + public static contextValue: string = "cosmosDBStoredProcedure"; + public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; + public readonly cTime: number = Date.now(); + public readonly parent: DocDBStoredProceduresTreeItem; + public mTime: number = Date.now(); - constructor( - parent: DocDBStoredProceduresTreeItem, - public procedure: StoredProcedureDefinition & Resource - ) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = "cosmosDB.openStoredProcedure"; - } + constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { + super(parent); + ext.fileSystem.fireChangedEvent(this); + this.commandId = 'cosmosDB.openStoredProcedure'; + } - public get root(): IDocDBTreeRoot { - return this.parent.root; - } + public get root(): IDocDBTreeRoot { + return this.parent.root; + } - public get filePath(): string { - return this.label + "-cosmos-stored-procedure.js"; - } + public get filePath(): string { + return this.label + '-cosmos-stored-procedure.js'; + } - public get id(): string { - return this.procedure.id; - } + public get id(): string { + return this.procedure.id; + } - public get label(): string { - return this.procedure.id; - } + public get label(): string { + return this.procedure.id; + } - public get link(): string { - return this.procedure._self; - } + public get link(): string { + return this.procedure._self; + } - public async getFileContent(): Promise { - return typeof this.procedure.body === "string" - ? this.procedure.body - : ""; - } + public async getFileContent(): Promise { + return typeof this.procedure.body === 'string' ? this.procedure.body : ''; - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } + } - public async writeFileContent( - _context: IActionContext, - content: string - ): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent - .getContainerClient(client) - .scripts.storedProcedure(this.id) - .replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, "resource"); - } + public async refreshImpl(): Promise { + ext.fileSystem.fireChangedEvent(this); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("server-process"); - } + public async writeFileContent(_context: IActionContext, content: string): Promise { + const client = this.root.getCosmosClient(); + const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); + this.procedure = nonNullProp(replace, 'resource'); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteStoredProcedure" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.parent - .getContainerClient(client) - .scripts.storedProcedure(this.id) - .delete(); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('server-process'); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); + } } diff --git a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts index a869e8a99..4c3ddfd1a 100644 --- a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts @@ -3,141 +3,95 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - CosmosClient, - FeedOptions, - QueryIterator, - Resource, - StoredProcedureDefinition, -} from "@azure/cosmos"; -import { - AzExtTreeItem, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; +import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; +import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; import * as vscode from "vscode"; -import { defaultStoredProcedure } from "../../constants"; -import { GraphCollectionTreeItem } from "../../graph/tree/GraphCollectionTreeItem"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; -import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; +import { defaultStoredProcedure } from '../../constants'; +import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; +import { localize } from '../../utils/localize'; +import { nonNullProp } from '../../utils/nonNull'; +import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; +import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { DocDBTreeItemBase } from './DocDBTreeItemBase'; /** * This class represents the DocumentDB "Stored Procedures" node in the tree */ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = - DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild( - resource: StoredProcedureDefinition & Resource - ): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("server-process"); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = - await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = ( - await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: "createStoredProcedure", - validateInput: (name: string) => - this.validateStoredProcedureName( - name, - currStoredProcedureNames - ), - }) - ).trim(); - const body: StoredProcedureDefinition = { - id: spID, - body: defaultStoredProcedure, - }; - context.showCreatingTreeItem(spID); - const sproc = - await this.getContainerClient( - client - ).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, "resource")); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll( - feedOptions - ); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName( - name: string, - currStoredProcedureNames: string[] - ): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize( - "nameLength", - "Name has to be between 1 and 255 chars long" - ); - } - - if (/[/\\?#&]/.test(name)) { - return localize( - "illegalChars", - "Name contains illegal chars: /, \\, ?, #, &" - ); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize( - "nameExists", - 'Stored Procedure "{0}" already exists.', - name - ); - } - - return undefined; - } + + public static contextValue: string = "cosmosDBStoredProceduresGroup"; + public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; + public readonly childTypeLabel: string = "Stored Procedure"; + public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { + return new DocDBStoredProcedureTreeItem(this, resource); + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('server-process'); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + const client = this.root.getCosmosClient(); + const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); + const currStoredProcedureNames: string[] = []; + for (const sp of currStoredProcedureList) { + currStoredProcedureNames.push(nonNullProp(sp, "id")); + } + const spID = (await context.ui.showInputBox({ + prompt: "Enter a unique stored procedure ID", + stepName: 'createStoredProcedure', + validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) + })).trim(); + const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; + context.showCreatingTreeItem(spID); + const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); + + return this.initChild(nonNullProp(sproc, 'resource')); + } + + public get id(): string { + return "$StoredProcedures"; + } + + public get label(): string { + return "Stored Procedures"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { + return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { + if (name.length < 1 || name.length > 255) { + return localize("nameLength", "Name has to be between 1 and 255 chars long"); + } + + if (/[/\\?#&]/.test(name)) { + return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); + } + if (name[name.length - 1] === " ") { + return localize("endsWithSpace", "Name cannot end with a space."); + } + if (currStoredProcedureNames.includes(name)) { + return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); + } + + return undefined; + } } diff --git a/Source/docdb/tree/DocDBTreeItemBase.ts b/Source/docdb/tree/DocDBTreeItemBase.ts index 0774fbcdc..4424603ae 100644 --- a/Source/docdb/tree/DocDBTreeItemBase.ts +++ b/Source/docdb/tree/DocDBTreeItemBase.ts @@ -3,64 +3,53 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, FeedOptions, QueryIterator } from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, -} from "@microsoft/vscode-azext-utils"; -import { getBatchSizeSetting } from "../../utils/workspacUtils"; -import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; +import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; +import { getBatchSizeSetting } from '../../utils/workspacUtils'; +import { IDocDBTreeRoot } from './IDocDBTreeRoot'; /** * This class provides common iteration logic for DocumentDB accounts, databases, and collections */ export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; + public abstract readonly label: string; + public abstract readonly contextValue: string; + public abstract readonly childTypeLabel: string; - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); + private _hasMoreChildren: boolean = true; + private _iterator: QueryIterator | undefined; + private _batchSize: number = getBatchSizeSetting(); - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } - public root: IDocDBTreeRoot; + public root: IDocDBTreeRoot; - public abstract initChild(resource: T): AzExtTreeItem; + public abstract initChild(resource: T): AzExtTreeItem; - public abstract getIterator( - client: CosmosClient, - feedOptions: FeedOptions - ): QueryIterator; + public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + } - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { - maxItemCount: this._batchSize, - }); - } + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (clearCache || this._iterator === undefined) { + this._hasMoreChildren = true; + const client = this.root.getCosmosClient(); + this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); + } - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()) - .resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); + const resourceArray: T[] = []; + const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; + if (resourceFeed) { + resourceArray.push(...resourceFeed); + } + this._hasMoreChildren = this._iterator.hasMoreResults(); - this._batchSize *= 2; + this._batchSize *= 2; - return resourceArray.map((resource: T) => this.initChild(resource)); - } + return resourceArray.map((resource: T) => this.initChild(resource)); + } } diff --git a/Source/docdb/tree/DocDBUtils.ts b/Source/docdb/tree/DocDBUtils.ts index 1a0630d53..3d45cf950 100644 --- a/Source/docdb/tree/DocDBUtils.ts +++ b/Source/docdb/tree/DocDBUtils.ts @@ -8,5 +8,5 @@ * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding */ export function sanitizeId(id: string): string { - return id.replace(/\+/g, " "); + return id.replace(/\+/g, ' '); } diff --git a/Source/docdb/tree/IDocDBTreeRoot.ts b/Source/docdb/tree/IDocDBTreeRoot.ts index 6827564c2..9179eb454 100644 --- a/Source/docdb/tree/IDocDBTreeRoot.ts +++ b/Source/docdb/tree/IDocDBTreeRoot.ts @@ -1,3 +1,4 @@ + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -6,8 +7,8 @@ import { CosmosClient } from "@azure/cosmos"; export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; + endpoint: string; + masterKey: string; + isEmulator: boolean | undefined; + getCosmosClient(): CosmosClient; } diff --git a/Source/extension.ts b/Source/extension.ts index c712fbc4c..e68744157 100644 --- a/Source/extension.ts +++ b/Source/extension.ts @@ -3,409 +3,213 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -"use strict"; - -import { registerAzureUtilsExtensionVariables } from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - AzureExtensionApi, - IActionContext, - ITreeItemPickerContext, - apiUtils, - callWithTelemetryAndErrorHandling, - createApiProvider, - createAzExtOutputChannel, - registerCommandWithTreeNodeUnwrapping, - registerErrorHandler, - registerEvent, - registerReportIssueCommand, - registerUIExtensionVariables, -} from "@microsoft/vscode-azext-utils"; -import { AzExtResourceType } from "@microsoft/vscode-azureresources-api"; -import { platform } from "os"; -import * as vscode from "vscode"; -import { DatabasesFileSystem } from "./DatabasesFileSystem"; -import { findTreeItem } from "./commands/api/findTreeItem"; -import { pickTreeItem } from "./commands/api/pickTreeItem"; -import { revealTreeItem } from "./commands/api/revealTreeItem"; -import { deleteDatabaseAccount } from "./commands/deleteDatabaseAccount/deleteDatabaseAccount"; -import { importDocuments } from "./commands/importDocuments"; -import { - cosmosGremlinFilter, - cosmosMongoFilter, - cosmosTableFilter, - doubleClickDebounceDelay, - sqlFilter, -} from "./constants"; -import { registerDocDBCommands } from "./docdb/registerDocDBCommands"; -import { DocDBAccountTreeItem } from "./docdb/tree/DocDBAccountTreeItem"; -import { DocDBAccountTreeItemBase } from "./docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBCollectionTreeItem } from "./docdb/tree/DocDBCollectionTreeItem"; -import { DocDBDocumentTreeItem } from "./docdb/tree/DocDBDocumentTreeItem"; -import { ext } from "./extensionVariables"; -import { getResourceGroupsApi } from "./getExtensionApi"; -import { registerGraphCommands } from "./graph/registerGraphCommands"; -import { GraphAccountTreeItem } from "./graph/tree/GraphAccountTreeItem"; -import { registerMongoCommands } from "./mongo/registerMongoCommands"; -import { setConnectedNode } from "./mongo/setConnectedNode"; -import { MongoAccountTreeItem } from "./mongo/tree/MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./mongo/tree/MongoCollectionTreeItem"; -import { MongoDocumentTreeItem } from "./mongo/tree/MongoDocumentTreeItem"; -import { registerPostgresCommands } from "./postgres/commands/registerPostgresCommands"; -import { DatabaseResolver } from "./resolver/AppResolver"; -import { DatabaseWorkspaceProvider } from "./resolver/DatabaseWorkspaceProvider"; -import { TableAccountTreeItem } from "./table/tree/TableAccountTreeItem"; -import { AttachedAccountSuffix } from "./tree/AttachedAccountsTreeItem"; -import { SubscriptionTreeItem } from "./tree/SubscriptionTreeItem"; -import { localize } from "./utils/localize"; - -const cosmosDBTopLevelContextValues: string[] = [ - GraphAccountTreeItem.contextValue, - DocDBAccountTreeItem.contextValue, - TableAccountTreeItem.contextValue, - MongoAccountTreeItem.contextValue, -]; - -export async function activateInternal( - context: vscode.ExtensionContext, - perfStats: { loadStartTime: number; loadEndTime: number }, - ignoreBundle?: boolean -): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling( - "cosmosDB.activate", - async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = "true"; - activateContext.telemetry.measurements.mainFileLoad = - (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver( - AzExtResourceType.AzureCosmosDb, - new DatabaseResolver() - ); - ext.rgApi.registerApplicationResourceResolver( - AzExtResourceType.PostgresqlServersStandard, - new DatabaseResolver() - ); - ext.rgApi.registerApplicationResourceResolver( - AzExtResourceType.PostgresqlServersFlexible, - new DatabaseResolver() - ); - - const workspaceRootTreeItem = ( - ext.rgApi.workspaceResourceTree as unknown as { - _rootTreeItem: AzExtParentTreeItem; - } - )._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider( - workspaceRootTreeItem - ); - ext.rgApi.registerWorkspaceResourceProvider( - "AttachedDatabaseAccount", - databaseWorkspaceProvider - ); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push( - vscode.workspace.registerFileSystemProvider( - DatabasesFileSystem.scheme, - ext.fileSystem - ) - ); - - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.selectSubscriptions", - () => - vscode.commands.executeCommand( - "azure-account.selectSubscriptions" - ) - ); - - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.createServer", - createServer - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteAccount", - deleteAccount - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.attachDatabaseAccount", - async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount( - actionContext - ); - await ext.rgApi.workspaceResourceTree.refresh( - actionContext, - ext.attachedAccountsNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.attachEmulator", - async (actionContext: IActionContext) => { - if (platform() !== "win32") { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error( - localize( - "emulatorNotSupported", - "The Cosmos DB emulator is only supported on Windows." - ) - ); - } - - await ext.attachedAccountsNode.attachEmulator( - actionContext - ); - await ext.rgApi.workspaceResourceTree.refresh( - actionContext, - ext.attachedAccountsNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.refresh", - async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh( - actionContext, - node - ); - } - } - ); - - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.detachDatabaseAccount", - async ( - actionContext: IActionContext & ITreeItemPickerContext, - node?: AzExtTreeItem - ) => { - const children = - await ext.attachedAccountsNode.loadAllChildren( - actionContext - ); - if ( - children[0].contextValue === - "cosmosDBAttachDatabaseAccount" - ) { - const message = localize( - "noAttachedAccounts", - "There are no Attached Accounts." - ); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = - await ext.rgApi.workspaceResourceTree.showTreeItemPicker( - cosmosDBTopLevelContextValues.map( - (val: string) => - (val += AttachedAccountSuffix) - ), - actionContext - ); - } - if (node instanceof MongoAccountTreeItem) { - if ( - ext.connectedMongoDB && - node.fullId === - ext.connectedMongoDB.parent.fullId - ) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh( - actionContext, - ext.attachedAccountsNode - ); - } - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.importDocument", - async ( - actionContext: IActionContext, - selectedNode: - | vscode.Uri - | MongoCollectionTreeItem - | DocDBCollectionTreeItem, - uris: vscode.Uri[] - ) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments( - actionContext, - uris || [selectedNode], - undefined - ); - } else { - await importDocuments( - actionContext, - undefined, - selectedNode - ); - } - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.copyConnectionString", - cosmosDBCopyConnectionString - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openDocument", - async ( - actionContext: IActionContext, - node?: MongoDocumentTreeItem | DocDBDocumentTreeItem - ) => { - if (!node) { - node = await ext.rgApi.pickAppResource< - MongoDocumentTreeItem | DocDBDocumentTreeItem - >(actionContext, { - filter: [cosmosMongoFilter, sqlFilter], - expectedChildContextValue: [ - MongoDocumentTreeItem.contextValue, - DocDBDocumentTreeItem.contextValue, - ], - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.update", - async (_actionContext: IActionContext, uri: vscode.Uri) => - await ext.fileSystem.updateWithoutPrompt(uri) - ); - registerCommandWithTreeNodeUnwrapping( - "azureDatabases.loadMore", - async (actionContext: IActionContext, node: AzExtTreeItem) => - await ext.rgApi.appResourceTree.loadMore( - node, - actionContext - ) - ); - registerEvent( - "cosmosDB.onDidChangeConfiguration", - vscode.workspace.onDidChangeConfiguration, - async ( - actionContext: IActionContext, - event: vscode.ConfigurationChangeEvent - ) => { - actionContext.telemetry.properties.isActivationEvent = - "true"; - actionContext.errorHandling.suppressDisplay = true; - if ( - event.affectsConfiguration( - ext.settingsKeys.documentLabelFields - ) - ) { - await vscode.commands.executeCommand( - "azureDatabases.refresh" - ); - } - } - ); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler( - (c) => (c.errorHandling.suppressReportIssue = true) - ); - registerReportIssueCommand("azureDatabases.reportIssue"); - } - ); - - return createApiProvider([ - { - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: "1.2.0", - }, - ]); +'use strict'; + +import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; +import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; +import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; +import { platform } from 'os'; +import * as vscode from 'vscode'; +import { DatabasesFileSystem } from './DatabasesFileSystem'; +import { findTreeItem } from './commands/api/findTreeItem'; +import { pickTreeItem } from './commands/api/pickTreeItem'; +import { revealTreeItem } from './commands/api/revealTreeItem'; +import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; +import { importDocuments } from './commands/importDocuments'; +import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; +import { registerDocDBCommands } from './docdb/registerDocDBCommands'; +import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; +import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; +import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; +import { ext } from './extensionVariables'; +import { getResourceGroupsApi } from './getExtensionApi'; +import { registerGraphCommands } from './graph/registerGraphCommands'; +import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; +import { registerMongoCommands } from './mongo/registerMongoCommands'; +import { setConnectedNode } from './mongo/setConnectedNode'; +import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; +import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; +import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; +import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; +import { DatabaseResolver } from './resolver/AppResolver'; +import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; +import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; +import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; +import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; +import { localize } from './utils/localize'; + +const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; + +export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { + ext.context = context; + ext.ignoreBundle = ignoreBundle; + + ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); + context.subscriptions.push(ext.outputChannel); + registerUIExtensionVariables(ext); + registerAzureUtilsExtensionVariables(ext); + + await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { + activateContext.telemetry.properties.isActivationEvent = 'true'; + activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; + + ext.secretStorage = context.secrets; + + ext.rgApi = await getResourceGroupsApi(); + ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); + ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); + ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); + + const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; + const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); + ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); + + ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); + + registerDocDBCommands(); + registerGraphCommands(); + registerPostgresCommands(); + registerMongoCommands(); + + context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); + + registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); + + registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); + registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { + await ext.attachedAccountsNode.attachNewAccount(actionContext); + await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { + if (platform() !== 'win32') { + actionContext.errorHandling.suppressReportIssue = true; + throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); + } + + await ext.attachedAccountsNode.attachEmulator(actionContext); + await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); + }); + registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { + if (node) { + await node.refresh(actionContext); + } else { + await ext.rgApi.appResourceTree.refresh(actionContext, node); + } + }); + + registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { + const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); + if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { + const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); + void vscode.window.showInformationMessage(message); + } else { + if (!node) { + node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); + } + if (node instanceof MongoAccountTreeItem) { + if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { + setConnectedNode(undefined); + await node.refresh(actionContext); + } + } + await ext.attachedAccountsNode.detach(node); + await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); + } + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { + if (selectedNode instanceof vscode.Uri) { + await importDocuments(actionContext, uris || [selectedNode], undefined); + } else { + await importDocuments(actionContext, undefined, selectedNode); + } + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { + if (!node) { + node = await ext.rgApi.pickAppResource(actionContext, { + filter: [ + cosmosMongoFilter, + sqlFilter + ], + expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] + }); + } + + // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 + ext.fileSystem.fireChangedEvent(node); + await ext.fileSystem.showTextDocument(node); + }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); + registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); + registerEvent( + 'cosmosDB.onDidChangeConfiguration', + vscode.workspace.onDidChangeConfiguration, + async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { + actionContext.telemetry.properties.isActivationEvent = "true"; + actionContext.errorHandling.suppressDisplay = true; + if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { + await vscode.commands.executeCommand("azureDatabases.refresh"); + } + }); + + // Suppress "Report an Issue" button for all errors in favor of the command + registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); + registerReportIssueCommand('azureDatabases.reportIssue'); + }); + + return createApiProvider([{ + findTreeItem, + pickTreeItem, + revealTreeItem, + apiVersion: '1.2.0' + }]); } // this method is called when your extension is deactivated export function deactivateInternal(): void { - // NOOP + // NOOP } -export async function createServer( - context: IActionContext, - node?: SubscriptionTreeItem -): Promise { - if (!node) { - node = - await ext.rgApi.appResourceTree.showTreeItemPicker( - SubscriptionTreeItem.contextValue, - context - ); - } +export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { + if (!node) { + node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); + } - await SubscriptionTreeItem.createChild(context, node); + await SubscriptionTreeItem.createChild(context, node); } -export async function deleteAccount( - context: IActionContext, - node?: AzExtTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter, - ], - }); - } - - await deleteDatabaseAccount(context, node, false); +export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter + ] + }); + } + + await deleteDatabaseAccount(context, node, false) } -export async function cosmosDBCopyConnectionString( - context: IActionContext, - node?: MongoAccountTreeItem | DocDBAccountTreeItemBase -): Promise { - const message = "The connection string has been copied to the clipboard"; - if (!node) { - node = await ext.rgApi.pickAppResource< - MongoAccountTreeItem | DocDBAccountTreeItemBase - >(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter, - ], - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); +export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { + const message = 'The connection string has been copied to the clipboard'; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter + ] + }); + } + + await vscode.env.clipboard.writeText(node.connectionString); + void vscode.window.showInformationMessage(message); } diff --git a/Source/extensionVariables.ts b/Source/extensionVariables.ts index 3af61432c..4a3fc2650 100644 --- a/Source/extensionVariables.ts +++ b/Source/extensionVariables.ts @@ -3,11 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeDataProvider, - AzExtTreeItem, - IAzExtOutputChannel, -} from "@microsoft/vscode-azext-utils"; +import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { ExtensionContext, SecretStorage, TreeView } from "vscode"; import { DatabasesFileSystem } from "./DatabasesFileSystem"; @@ -23,34 +19,33 @@ import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWit * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts */ export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = "azureDatabases"; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; + export let connectedMongoDB: MongoDatabaseTreeItem | undefined; + export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; + export let context: ExtensionContext; + export let outputChannel: IAzExtOutputChannel; + export let tree: AzExtTreeDataProvider; + export let treeView: TreeView; + export let attachedAccountsNode: AttachedAccountsTreeItem; + export let ignoreBundle: boolean | undefined; + export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; + export let secretStorage: SecretStorage; + export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; + export const prefix: string = 'azureDatabases'; + export let fileSystem: DatabasesFileSystem; + export let mongoCodeLensProvider: MongoCodeLensProvider; + export let mongoLanguageClient: MongoDBLanguageClient; + export let rgApi: AzureHostExtensionApi; - export namespace settingsKeys { - export const mongoShellPath = "mongo.shell.path"; - export const mongoShellArgs = "mongo.shell.args"; - export const documentLabelFields = "cosmosDB.documentLabelFields"; - export const enableEndpointDiscovery = - "cosmosDB.enableEndpointDiscovery"; - export const mongoShellTimeout = "mongo.shell.timeout"; - export const batchSize = "azureDatabases.batchSize"; + export namespace settingsKeys { + export const mongoShellPath = 'mongo.shell.path'; + export const mongoShellArgs = 'mongo.shell.args'; + export const documentLabelFields = 'cosmosDB.documentLabelFields'; + export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; + export const mongoShellTimeout = 'mongo.shell.timeout'; + export const batchSize = 'azureDatabases.batchSize'; - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } + export namespace vsCode { + export const proxyStrictSSL = "http.proxyStrictSSL"; + } + } } diff --git a/Source/getExtensionApi.ts b/Source/getExtensionApi.ts index 63efdb7e5..bfd553e74 100644 --- a/Source/getExtensionApi.ts +++ b/Source/getExtensionApi.ts @@ -8,35 +8,24 @@ import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { Extension, extensions } from "vscode"; import { localize } from "./utils/localize"; -export async function getApiExport( - extensionId: string -): Promise { - const extension: Extension | undefined = - extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } +export async function getApiExport(extensionId: string): Promise { + const extension: Extension | undefined = extensions.getExtension(extensionId); + if (extension) { + if (!extension.isActive) { + await extension.activate(); + } - return extension.exports; - } + return extension.exports; + } - return undefined; + return undefined; } export async function getResourceGroupsApi(): Promise { - const rgApiProvider = - await getApiExport( - "ms-azuretools.vscode-azureresourcegroups" - ); - if (rgApiProvider) { - return rgApiProvider.getApi("0.0.1"); - } else { - throw new Error( - localize( - "noResourceGroupExt", - "Could not find the Azure Resource Groups extension" - ) - ); - } + const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); + if (rgApiProvider) { + return rgApiProvider.getApi('0.0.1'); + } else { + throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); + } } diff --git a/Source/graph/gremlinEndpoints.ts b/Source/graph/gremlinEndpoints.ts index 0bbeae16f..1ef6b283d 100644 --- a/Source/graph/gremlinEndpoints.ts +++ b/Source/graph/gremlinEndpoints.ts @@ -3,50 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { nonNullValue } from "../utils/nonNull"; -import { IGremlinEndpoint } from "../vscode-cosmosdbgraph.api"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { nonNullValue } from '../utils/nonNull'; +import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; -export async function tryGetGremlinEndpointFromAzure( - client: CosmosDBManagementClient, - resourceGroup: string, - account: string -): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; +export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { + // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk + const response = await client.databaseAccounts.get(resourceGroup, account); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const endpointUri = response.documentEndpoint; + // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint + return endpointUri ? parseEndpointUrl(endpointUri) : undefined; } -export function getPossibleGremlinEndpoints( - documentEndpoint: string -): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ +export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { + // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - const documentSuffix = ".documents.azure.com"; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace( - documentSuffix, - ".graphs.azure.com" - ); + const documentSuffix = '.documents.azure.com'; + if (documentEndpoint.indexOf(documentSuffix) >= 0) { + // Pre-GA style (Dec 2017) + const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace( - documentSuffix, - ".gremlin.cosmosdb.azure.com" - ); + // Post-GA style (Dec 2017) + const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); - return [ - parseEndpointUrl(postGAEndpoint), - parseEndpointUrl(preGAEndpoint), - ]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } + return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; + } else { + console.warn(`Unexpected document URL format: ${documentEndpoint}`); + return [parseEndpointUrl(documentEndpoint)]; + } } /** @@ -54,12 +39,9 @@ export function getPossibleGremlinEndpoints( * @param url An account URL such as 'https://.documents.azure.com:443/' */ function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue( - url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), - "urlMatch" - ); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; + const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); + console.assert(!!protocol && !!host, "Unexpected endpoint format"); + const port = parseInt(portString || "443", 10); + console.assert(port > 0, "Unexpected port"); + return { host, port, ssl: protocol.toLowerCase() === "https" }; } diff --git a/Source/graph/registerGraphCommands.ts b/Source/graph/registerGraphCommands.ts index 21e05d9a5..1746c638b 100644 --- a/Source/graph/registerGraphCommands.ts +++ b/Source/graph/registerGraphCommands.ts @@ -3,97 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - IActionContext, - ITreeItemPickerContext, - registerCommandWithTreeNodeUnwrapping, -} from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from "../constants"; -import { ext } from "../extensionVariables"; +import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; +import { ext } from '../extensionVariables'; import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; import { GraphTreeItem } from "./tree/GraphTreeItem"; export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createGraphDatabase", - createGraphDatabase - ); - registerCommandWithTreeNodeUnwrapping("cosmosDB.createGraph", createGraph); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteGraphDatabase", - async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph( - context, - GraphDatabaseTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteGraph", - async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph( - context, - GraphCollectionTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openGraphExplorer", - async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph( - context, - GraphTreeItem.contextValue - ); - } - await node.showExplorer(context); - }, - doubleClickDebounceDelay - ); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph(context, GraphCollectionTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { + if (!node) { + node = await pickGraph(context, GraphTreeItem.contextValue); + } + await node.showExplorer(context); + }, doubleClickDebounceDelay); } -export async function createGraphDatabase( - context: IActionContext, - node?: GraphAccountTreeItem -): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); +export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { + if (!node) { + node = await pickGraph(context); + } + await node.createChild(context); } -export async function createGraph( - context: IActionContext, - node?: GraphDatabaseTreeItem -): Promise { - if (!node) { - node = await pickGraph( - context, - GraphDatabaseTreeItem.contextValue - ); - } - await node.createChild(context); +export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { + if (!node) { + node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); + } + await node.createChild(context); } -async function pickGraph( - context: IActionContext, - expectedContextValue?: string | RegExp | (string | RegExp)[] -): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [cosmosGremlinFilter], - expectedChildContextValue: expectedContextValue, - }); +async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosGremlinFilter + ], + expectedChildContextValue: expectedContextValue + }); } diff --git a/Source/graph/tree/GraphAccountTreeItem.ts b/Source/graph/tree/GraphAccountTreeItem.ts index 8025e4f8e..7e1f561fa 100644 --- a/Source/graph/tree/GraphAccountTreeItem.ts +++ b/Source/graph/tree/GraphAccountTreeItem.ts @@ -3,62 +3,43 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { DatabaseDefinition, Resource } from "@azure/cosmos"; -import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; -import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; -import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; -import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; -import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./GraphTreeItem"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { DatabaseDefinition, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; +import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; +import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; +import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; +import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; +import { GraphTreeItem } from './GraphTreeItem'; export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBGraphAccount"; + public contextValue: string = GraphAccountTreeItem.contextValue; - constructor( - parent: AzExtParentTreeItem, - id: string, - label: string, - documentEndpoint: string, - private _gremlinEndpoint: IGremlinEndpoint | undefined, - masterKey: string, - isEmulator: boolean | undefined, - readonly databaseAccount?: DatabaseAccountGetResults - ) { - super( - parent, - id, - label, - documentEndpoint, - masterKey, - isEmulator, - databaseAccount - ); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } + constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { + super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); + this.valuesToMask.push(documentEndpoint); + if (_gremlinEndpoint) { + this.valuesToMask.push(_gremlinEndpoint.host); + } + } - public initChild( - database: DatabaseDefinition & Resource - ): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } + public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { + return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case GraphDatabaseTreeItem.contextValue: + case GraphCollectionTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case GraphTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/graph/tree/GraphCollectionTreeItem.ts b/Source/graph/tree/GraphCollectionTreeItem.ts index efc25ae4c..63709d977 100644 --- a/Source/graph/tree/GraphCollectionTreeItem.ts +++ b/Source/graph/tree/GraphCollectionTreeItem.ts @@ -3,108 +3,85 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - Container, - ContainerDefinition, - CosmosClient, - Resource, -} from "@azure/cosmos"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; -import { IDocDBTreeRoot } from "../../docdb/tree/IDocDBTreeRoot"; -import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./GraphTreeItem"; +import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; +import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; +import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; +import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; +import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; +import { GraphTreeItem } from './GraphTreeItem'; export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor( - parent: GraphDatabaseTreeItem, - collection: ContainerDefinition & Resource - ) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( - this - ); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteGraphCollection" }, - DialogResponses.deleteResponse - ); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl( - expectedContextValues: (string | RegExp)[] - ): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getDatabaseClient(client).container(this.id); - } + public static contextValue: string = "cosmosDBGraph"; + public readonly contextValue: string = GraphCollectionTreeItem.contextValue; + public readonly parent: GraphDatabaseTreeItem; + + private readonly _graphTreeItem: GraphTreeItem; + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + private readonly _collection: ContainerDefinition & Resource; + + constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { + super(parent); + this._collection = collection; + this._graphTreeItem = new GraphTreeItem(this, this._collection); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return this._collection.id; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + return [this._graphTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case GraphTreeItem.contextValue: + return this._graphTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return (this.parent.getDatabaseClient(client)).container(this.id); + + } } diff --git a/Source/graph/tree/GraphDatabaseTreeItem.ts b/Source/graph/tree/GraphDatabaseTreeItem.ts index 4fc7a9655..1c5332700 100644 --- a/Source/graph/tree/GraphDatabaseTreeItem.ts +++ b/Source/graph/tree/GraphDatabaseTreeItem.ts @@ -3,76 +3,63 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ContainerDefinition, - CosmosClient, - Database, - DatabaseDefinition, - Resource, -} from "@azure/cosmos"; -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; -import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; -import { getPossibleGremlinEndpoints } from "../gremlinEndpoints"; -import { GraphAccountTreeItem } from "./GraphAccountTreeItem"; -import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; +import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; +import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; +import { GraphAccountTreeItem } from './GraphAccountTreeItem'; +import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Graph"; + public static contextValue: string = "cosmosDBGraphDatabase"; + public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = 'Graph'; - constructor( - parent: GraphAccountTreeItem, - private _gremlinEndpoint: IGremlinEndpoint | undefined, - database: DatabaseDefinition & Resource - ) { - super(parent, database); - } + constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { + super(parent, database); + } - public initChild( - collection: ContainerDefinition & Resource - ): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } + public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { + return new GraphCollectionTreeItem(this, collection); + } - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } + // Gremlin endpoint, if definitely known + get gremlinEndpoint(): IGremlinEndpoint | undefined { + return this._gremlinEndpoint; + } - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } + get possibleGremlinEndpoints(): IGremlinEndpoint[] { + return getPossibleGremlinEndpoints(this.root.endpoint); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); - protected override async getNewPartitionKey( - context: IActionContext - ): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: "Enter the partition key for the collection, or leave blank for fixed size.", - stepName: "partitionKeyForCollection", - validateInput: this.validatePartitionKey, - placeHolder: "e.g. /address", - }); + } - if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { - partitionKey = "/" + partitionKey; - } + protected override async getNewPartitionKey(context: IActionContext): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', + stepName: 'partitionKeyForCollection', + validateInput: this.validatePartitionKey, + placeHolder: 'e.g. /address' + }); - return partitionKey; - } + if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { + partitionKey = '/' + partitionKey; + } - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + if (/.+\//.test(key)) { + return "Cannot be a nested path"; + } + return undefined; + } } diff --git a/Source/graph/tree/GraphTreeItem.ts b/Source/graph/tree/GraphTreeItem.ts index d98da8b6b..800fded5a 100644 --- a/Source/graph/tree/GraphTreeItem.ts +++ b/Source/graph/tree/GraphTreeItem.ts @@ -3,65 +3,54 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, Resource } from "@azure/cosmos"; -import { - AzExtTreeItem, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { localize } from "../../utils/localize"; -import { openUrl } from "../../utils/openUrl"; -import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { ContainerDefinition, Resource } from '@azure/cosmos'; +import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { localize } from '../../utils/localize'; +import { openUrl } from '../../utils/openUrl'; +import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -const alternativeGraphVisualizationToolsDocLink = - "https://aka.ms/cosmosdb-graph-alternative-tools"; +const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor( - parent: GraphCollectionTreeItem, - collection: ContainerDefinition & Resource - ) { - super(parent); - this.commandId = "cosmosDB.openGraphExplorer"; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize( - "mustInstallGraph", - "Cosmos DB Graph extension has been retired." - ); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } + public static contextValue: string = "cosmosDBGraphGraph"; + public readonly contextValue: string = GraphTreeItem.contextValue; + public readonly parent: GraphCollectionTreeItem; + public suppressMaskLabel = true; + + private readonly _collection: ContainerDefinition & Resource; + + constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { + super(parent); + this.commandId = 'cosmosDB.openGraphExplorer'; + this._collection = collection; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return "Graph"; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public async showExplorer(_context: IActionContext): Promise { + const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); + const alternativeToolsOption = "Alternative Tools"; + const result = await vscode.window.showErrorMessage( + message, + alternativeToolsOption + ); + if (result === alternativeToolsOption) { + await openUrl(alternativeGraphVisualizationToolsDocLink); + } + } } diff --git a/Source/mongo/MongoCommand.ts b/Source/mongo/MongoCommand.ts index ea9466b45..79c33731f 100644 --- a/Source/mongo/MongoCommand.ts +++ b/Source/mongo/MongoCommand.ts @@ -3,22 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RecognitionException } from "antlr4ts"; -import * as vscode from "vscode"; +import { RecognitionException } from 'antlr4ts'; +import * as vscode from 'vscode'; export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; + range: vscode.Range; + text: string; + collection?: string; + name?: string; + arguments?: string[]; + argumentObjects?: Object[]; + errors?: ErrorDescription[]; + chained?: boolean; } export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; + range: vscode.Range; + message: string; + exception?: RecognitionException; } diff --git a/Source/mongo/MongoScrapbook.ts b/Source/mongo/MongoScrapbook.ts index 2f441285e..d5dfe6d00 100644 --- a/Source/mongo/MongoScrapbook.ts +++ b/Source/mongo/MongoScrapbook.ts @@ -3,718 +3,489 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - IActionContext, - IParsedError, - openReadOnlyContent, - parseError, - ReadOnlyContent, -} from "@microsoft/vscode-azext-utils"; -import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; -import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; -import { ErrorNode } from "antlr4ts/tree/ErrorNode"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ObjectID } from "bson"; -import { Collection } from "mongodb"; -import { EOL } from "os"; -import * as vscode from "vscode"; -import { ext } from "../extensionVariables"; -import { filterType, findType } from "../utils/array"; -import { localize } from "../utils/localize"; -import { nonNullProp, nonNullValue } from "../utils/nonNull"; -import { LexerErrorListener, ParserErrorListener } from "./errorListeners"; -import { mongoLexer } from "./grammar/mongoLexer"; -import * as mongoParser from "./grammar/mongoParser"; -import { MongoVisitor } from "./grammar/visitors"; -import { ErrorDescription, MongoCommand } from "./MongoCommand"; -import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; -import { - MongoDatabaseTreeItem, - stripQuotes, -} from "./tree/MongoDatabaseTreeItem"; -import { - IMongoDocument, - MongoDocumentTreeItem, -} from "./tree/MongoDocumentTreeItem"; +import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; +import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; +import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { ObjectID } from 'bson'; +import { Collection } from 'mongodb'; +import { EOL } from 'os'; +import * as vscode from 'vscode'; +import { ext } from '../extensionVariables'; +import { filterType, findType } from '../utils/array'; +import { localize } from '../utils/localize'; +import { nonNullProp, nonNullValue } from '../utils/nonNull'; +import { LexerErrorListener, ParserErrorListener } from './errorListeners'; +import { mongoLexer } from './grammar/mongoLexer'; +import * as mongoParser from './grammar/mongoParser'; +import { MongoVisitor } from './grammar/visitors'; +import { ErrorDescription, MongoCommand } from './MongoCommand'; +import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; +import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; +import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); -const notInScrapbookMessage = - "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument( - document: vscode.TextDocument -): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of command.errors || []) { - const diagnostic = new vscode.Diagnostic( - error.range, - error.message - ); - errors.push(diagnostic); - } - } - - return errors; +const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; + +export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { + const commands = getAllCommandsFromTextDocument(document); + const errors: vscode.Diagnostic[] = []; + for (const command of commands) { + for (const error of (command.errors || [])) { + const diagnostic = new vscode.Diagnostic(error.range, error.message); + errors.push(diagnostic); + } + } + + return errors; } -export async function executeAllCommandsFromActiveEditor( - context: IActionContext -): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); +export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { + ext.outputChannel.appendLog("Executing all commands in scrapbook..."); + const commands = getAllCommandsFromActiveEditor(); + await executeCommands(context, commands); } -export async function executeCommandFromActiveEditor( - context: IActionContext, - position?: vscode.Position -): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition( - commands, - position || vscode.window.activeTextEditor?.selection.start - ); - return await executeCommand(context, command); +export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { + const commands = getAllCommandsFromActiveEditor(); + const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); + return await executeCommand(context, command); } function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } + const activeEditor = vscode.window.activeTextEditor; + if (activeEditor) { + return getAllCommandsFromTextDocument(activeEditor.document); + } else { + // Shouldn't be able to reach this + throw new Error(notInScrapbookMessage); + } } -export function getAllCommandsFromTextDocument( - document: vscode.TextDocument -): MongoCommand[] { - return getAllCommandsFromText(document.getText()); +export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { + return getAllCommandsFromText(document.getText()); } -async function executeCommands( - context: IActionContext, - commands: MongoCommand[] -): Promise { - const label: string = "Scrapbook-execute-all-results"; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent( - { label, fullId }, - "", - ".txt", - { viewColumn: vscode.ViewColumn.Beside } - ); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split("(")[0]} at ${ - command.range.start.line + 1 - }:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } +async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { + const label: string = 'Scrapbook-execute-all-results'; + const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; + const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); + + for (const command of commands) { + try { + await executeCommand(context, command, readOnlyContent); + } catch (e) { + const err = parseError(e); + if (err.isUserCancelledError) { + throw e; + } else { + const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; + throw new Error(message); + } + } + } } -async function executeCommand( - context: IActionContext, - command: MongoCommand, - readOnlyContent?: ReadOnlyContent -): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String( - command.arguments ? command.arguments.length : 0 - ); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error( - 'Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item' - ); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error( - localize( - "unableToParseSyntax", - `Unable to parse syntax. Error near line ${ - err.range.start.line + 1 - }, column ${err.range.start.character + 1}: "${ - err.message - }"` - ) - ); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === "find" && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, "collection"); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem( - database, - collection, - command.argumentObjects - ); - await ext.fileSystem.showTextDocument(node, { - viewColumn: vscode.ViewColumn.Beside, - }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === "findOne") { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp( - command, - "collection" - ); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - collectionId, - context - ); - if (!colNode) { - throw new Error( - localize( - "failedToFind", - 'Failed to find collection "{0}".', - collectionName - ) - ); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { - viewColumn: vscode.ViewColumn.Beside, - }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = "Scrapbook-results"; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent( - { label, fullId }, - result, - ".json", - { viewColumn: vscode.ViewColumn.Beside } - ); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error( - "No MongoDB command found at the current cursor location." - ); - } +async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { + if (command) { + try { + context.telemetry.properties.command = command.name; + context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); + } catch (error) { + // Ignore + } + + const database = ext.connectedMongoDB; + if (!database) { + throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); + } + if (command.errors && command.errors.length > 0) { + //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. + const err = command.errors[0]; + throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); + } + + // we don't handle chained commands so we can only handle "find" if isn't chained + if (command.name === 'find' && !command.chained) { + const db = await database.connectToDb(); + const collectionName: string = nonNullProp(command, 'collection'); + const collection: Collection = db.collection(collectionName); + // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because + // the executed 'find' command could have a filter or projection that is not handled by a cached tree node + const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); + await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); + } else { + const result = await database.executeCommand(command, context); + if (command.name === 'findOne') { + if (result === "null") { + throw new Error(`Could not find any documents`); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const document: IMongoDocument = EJSON.parse(result); + const collectionName: string = nonNullProp(command, 'collection'); + + const collectionId: string = `${database.fullId}/${collectionName}`; + const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); + if (!colNode) { + throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); + } + const docNode = new MongoDocumentTreeItem(colNode, document); + await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); + } else { + if (readOnlyContent) { + await readOnlyContent.append(`${result}${EOL}${EOL}`); + } else { + const label: string = 'Scrapbook-results'; + const fullId: string = `${database.fullId}/${label}`; + await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); + } + + await refreshTreeAfterCommand(database, command, context); + } + } + } else { + throw new Error('No MongoDB command found at the current cursor location.'); + } } -async function refreshTreeAfterCommand( - database: MongoDatabaseTreeItem, - command: MongoCommand, - context: IActionContext -): Promise { - if (command.name === "drop") { - await database.refresh(context); - } else if ( - command.collection && - command.name && - /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test( - command.name - ) - ) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem( - database.fullId + "/" + command.collection, - context - ); - if (collectionNode) { - await collectionNode.refresh(context); - } - } +async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { + if (command.name === 'drop') { + await database.refresh(context); + } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { + const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); + if (collectionNode) { + await collectionNode.refresh(context); + } + } } export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = - parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition( - commands, - err.range.start - ); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "", - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; + const lexer = new mongoLexer(new InputStream(content)); + const lexerListener = new LexerErrorListener(); + lexer.removeErrorListeners(); // Default listener outputs to the console + lexer.addErrorListener(lexerListener); + const tokens: CommonTokenStream = new CommonTokenStream(lexer); + + const parser = new mongoParser.mongoParser(tokens); + const parserListener = new ParserErrorListener(); + parser.removeErrorListeners(); // Default listener outputs to the console + parser.addErrorListener(parserListener); + + const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); + const commands = new FindMongoCommandsVisitor().visit(commandsContext); + + // Match errors with commands based on location + const errors = lexerListener.errors.concat(parserListener.errors); + errors.sort((a, b) => { + const linediff = a.range.start.line - b.range.start.line; + const chardiff = a.range.start.character - b.range.start.character; + return linediff || chardiff; + }); + for (const err of errors) { + const associatedCommand = findCommandAtPosition(commands, err.range.start); + if (associatedCommand) { + associatedCommand.errors = associatedCommand.errors || []; + associatedCommand.errors.push(err); + } else { + // Create a new command to hook this up to + const emptyCommand: MongoCommand = { + collection: undefined, + name: undefined, + range: err.range, + text: "" + }; + emptyCommand.errors = [err]; + commands.push(emptyCommand); + } + } + + return commands; } -export function findCommandAtPosition( - commands: MongoCommand[], - position?: vscode.Position -): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return ( - lastCommandOnSameLine || - lastCommandBeforePosition || - commands[commands.length - 1] - ); +export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { + let lastCommandOnSameLine: MongoCommand | undefined; + let lastCommandBeforePosition: MongoCommand | undefined; + if (position) { + for (const command of commands) { + if (command.range.contains(position)) { + return command; + } + if (command.range.end.line === position.line) { + lastCommandOnSameLine = command; + } + if (command.range.end.isBefore(position)) { + lastCommandBeforePosition = command; + } + } + } + return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; } class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType( - ctx.children, - mongoParser.FunctionCallContext - ).length; - const stop = nonNullProp(ctx, "stop"); - this.commands.push({ - range: new vscode.Range( - ctx.start.line - 1, - ctx.start.charPositionInLine, - stop.line - 1, - stop.charPositionInLine - ), - text: ctx.text, - name: "", - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false, - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall( - ctx: mongoParser.FunctionCallContext - ): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = - (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if ( - functionCallContext && - functionCallContext.parent instanceof - mongoParser.CommandContext - ) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, "arguments").push(argText); - const escapeHandled = - this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { - //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, "argumentObjects").push( - ejsonParsed - ); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): Object { - if (!ctx || ctx.childCount === 0) { - //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, "children")[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand( - `Unrecognized node type encountered. We could not parse ${child.text}`, - ctx - ); - return {}; - } - } - - private literalContextToObject( - child: mongoParser.LiteralContext, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [ - mongoParser.mongoParser.NullLiteral, - mongoParser.mongoParser.BooleanLiteral, - mongoParser.mongoParser.NumericLiteral, - ]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand( - `Unrecognized token. Token text: ${text}`, - ctx - ); - return {}; - } - } - - private objectLiteralContextToObject( - child: mongoParser.ObjectLiteralContext - ): Object { - const propertyNameAndValue = findType( - child.children, - mongoParser.PropertyNameAndValueListContext - ); - if (!propertyNameAndValue) { - // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType( - propertyNameAndValue.children, - mongoParser.PropertyAssignmentContext - ); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp( - propertyAssignment, - "children" - ); - const propertyName = ( - propertyAssignmentChildren[0] - ); - const propertyValue = ( - propertyAssignmentChildren[2] - ); - parsedObject[stripQuotes(propertyName.text)] = - this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject( - child: mongoParser.ArrayLiteralContext - ) { - const elementList = findType( - child.children, - mongoParser.ElementListContext - ); - if (elementList) { - const elementItems = filterType( - elementList.children, - mongoParser.PropertyValueContext - ); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject( - child: mongoParser.FunctionCallContext, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue( - findType(functionTokens, TerminalNode), - "constructorCall" - ); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue( - findType(functionTokens, mongoParser.ArgumentsContext), - "argumentsToken" - ); - if ( - !( - argumentsToken._CLOSED_PARENTHESIS && - argumentsToken._OPEN_PARENTHESIS - ) - ) { - //argumentsToken does not have '(' or ')' - this.addErrorToCommand( - `Expecting parentheses or quotes at '${constructorCall.text}'`, - ctx - ); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType( - argumentsToken.children, - mongoParser.ArgumentContext - ); - if (argumentContextArray.length > 1) { - this.addErrorToCommand( - `Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, - ctx - ); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length - ? argumentContextArray[0].text - : undefined; - switch (constructorCall.text) { - case "ObjectId": - return this.objectIdToObject(ctx, tokenText); - case "ISODate": - return this.isodateToObject(ctx, tokenText); - case "Date": - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand( - `Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, - ctx - ); - return {}; - } - } - - private dateToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string - ): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string - ): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string, - isIsodate: boolean = false - ): Date | {} { - if (!tokenText) { - // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== "Z") { - tokenText += "Z"; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string - ): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { - // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - text: string - ): Object { - const separator = text.lastIndexOf("/"); - const flags = - separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { - $regex: this.regexToStringNotation(pattern), - $options: flags, - }; - } catch (error) { - //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand( - errorMessage: string, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext - ): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, "stop"); - const currentErrorDesc: ErrorDescription = { - message: errorMessage, - range: new vscode.Range( - ctx.start.line - 1, - ctx.start.charPositionInLine, - stop.line - 1, - stop.charPositionInLine - ), - }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, "\\\\$1"); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* + private commands: MongoCommand[] = []; + + public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { + const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; + const stop = nonNullProp(ctx, 'stop'); + this.commands.push({ + range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), + text: ctx.text, + name: '', + arguments: [], + argumentObjects: [], + chained: funcCallCount > 1 ? true : false + }); + return super.visitCommand(ctx); + } + + public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { + this.commands[this.commands.length - 1].collection = ctx.text; + return super.visitCollection(ctx); + } + + public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { + if (ctx.parent instanceof mongoParser.CommandContext) { + this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; + } + return super.visitFunctionCall(ctx); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { + try { + const argumentsContext = ctx.parent; + if (argumentsContext) { + const functionCallContext = argumentsContext.parent; + if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { + const lastCommand = this.commands[this.commands.length - 1]; + const argAsObject = this.contextToObject(ctx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const argText = EJSON.stringify(argAsObject); + nonNullProp(lastCommand, 'arguments').push(argText); + const escapeHandled = this.deduplicateEscapesForRegex(argText); + let ejsonParsed = {}; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + ejsonParsed = EJSON.parse(escapeHandled); + } catch (error) { //EJSON parse failed due to a wrong flag, etc. + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); + } + } + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + return super.visitArgument(ctx); + } + + protected defaultResult(_node: ParseTree): MongoCommand[] { + return this.commands; + } + + private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { + if (!ctx || ctx.childCount === 0) { //Base case and malformed statements + return {}; + } + // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 + const child: ParseTree = nonNullProp(ctx, 'children')[0]; + if (child instanceof mongoParser.LiteralContext) { + return this.literalContextToObject(child, ctx); + } else if (child instanceof mongoParser.ObjectLiteralContext) { + return this.objectLiteralContextToObject(child); + } else if (child instanceof mongoParser.ArrayLiteralContext) { + return this.arrayLiteralContextToObject(child); + } else if (child instanceof mongoParser.FunctionCallContext) { + return this.functionCallContextToObject(child, ctx); + } else if (child instanceof ErrorNode) { + return {}; + } else { + this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); + return {}; + } + } + + private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { + const text = child.text; + const tokenType = child.start.type; + const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; + if (tokenType === mongoParser.mongoParser.StringLiteral) { + return stripQuotes(text); + } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { + return this.regexLiteralContextToObject(ctx, text); + } else if (nonStringLiterals.indexOf(tokenType) > -1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return JSON.parse(text); + } else { + this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); + return {}; + } + } + + private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { + const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); + if (!propertyNameAndValue) { // Argument is {} + return {}; + } else { + const parsedObject: Object = {}; + const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); + for (const propertyAssignment of propertyAssignments) { + const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); + const propertyName = propertyAssignmentChildren[0]; + const propertyValue = propertyAssignmentChildren[2]; + parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); + } + return parsedObject; + } + } + + private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { + const elementList = findType(child.children, mongoParser.ElementListContext); + if (elementList) { + const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); + return elementItems.map(this.contextToObject.bind(this)); + } else { + return []; + } + } + + private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { + const functionTokens = child.children; + const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); + const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); + if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' + this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); + return {}; + } + + const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); + if (argumentContextArray.length > 1) { + this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); + return {}; + } + + const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; + switch (constructorCall.text) { + case 'ObjectId': + return this.objectIdToObject(ctx, tokenText); + case 'ISODate': + return this.isodateToObject(ctx, tokenText); + case 'Date': + return this.dateToObject(ctx, tokenText); + default: + this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); + return {}; + } + } + + private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText); + if (date instanceof Date) { + return { $date: date.toString() }; + } else { + return date; + } + } + + private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); + + if (date instanceof Date) { + return { $date: date.toISOString() }; + } else { + return date; + } + } + + private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { + if (!tokenText) { // usage : ObjectID() + return new Date(); + } else { + try { + tokenText = stripQuotes(tokenText); + + // if the tokenText was an isodate, the last char must be Z + if (isIsodate) { + if (tokenText[tokenText.length - 1] !== 'Z') { + tokenText += 'Z'; + } + } + + return new Date(tokenText); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + } + + private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { + let hexID: string; + let constructedObject: ObjectID; + if (!tokenText) { // usage : ObjectID() + constructedObject = new ObjectID(); + } else { + hexID = stripQuotes(tokenText); + try { + constructedObject = new ObjectID(hexID); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + return { $oid: constructedObject.toString() }; + } + + private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { + const separator = text.lastIndexOf('/'); + const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; + const pattern = text.substring(1, separator); + try { + // validate the pattern and flags. + // It is intended for the errors thrown here to be handled by the catch block. + let tokenObject = new RegExp(pattern, flags); + // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars + tokenObject = tokenObject; + // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax + return { $regex: this.regexToStringNotation(pattern), $options: flags }; + } catch (error) { //User may not have finished typing + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + + private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { + const command = this.commands[this.commands.length - 1]; + command.errors = command.errors || []; + const stop = nonNullProp(ctx, 'stop'); + const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; + command.errors.push(currentErrorDesc); + } + + private regexToStringNotation(pattern: string): string { + // The equivalence: + // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" + return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); + } + + private deduplicateEscapesForRegex(argAsString: string): string { + const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; + /* We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } + return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); + } + } diff --git a/Source/mongo/MongoShell.ts b/Source/mongo/MongoShell.ts index 81784f2af..b8f982ee8 100644 --- a/Source/mongo/MongoShell.ts +++ b/Source/mongo/MongoShell.ts @@ -3,216 +3,185 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from "os"; -import * as vscode from "vscode"; -import { InteractiveChildProcess } from "../utils/InteractiveChildProcess"; -import { randomUtils } from "../utils/randomUtils"; -import { getBatchSizeSetting } from "../utils/workspacUtils"; -import { wrapError } from "../utils/wrapError"; +import { parseError } from '@microsoft/vscode-azext-utils'; +import * as os from 'os'; +import * as vscode from 'vscode'; +import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; +import { randomUtils } from '../utils/randomUtils'; +import { getBatchSizeSetting } from '../utils/workspacUtils'; +import { wrapError } from '../utils/wrapError'; -const timeoutMessage = - "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; +const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = "(More)"; +const extensionMoreMessage = '(More)'; -const sentinelBase = "EXECUTION COMPLETED"; +const sentinelBase = 'EXECUTION COMPLETED'; const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { - return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; -} +function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } export class MongoShell extends vscode.Disposable { - constructor( - private _process: InteractiveChildProcess, - private _timeoutSeconds: number - ) { - super(() => this.dispose()); - } - - public static async create( - execPath: string, - execArgs: string[], - connectionString: string, - isEmulator: boolean | undefined, - outputChannel: vscode.OutputChannel, - timeoutSeconds: number - ): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = - await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: "", - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript( - `DBQuery.shellBatchSize = ${getBatchSizeSetting()}` - ); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise( - async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut((text) => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = - removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace( - mongoShellMoreMessage, - extensionMoreMessage - ); - - resolve(stdOutNoSentinel); - } - }) - ); - disposables.push( - this._process.onStdErr((text) => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - }) - ); - disposables.push( - this._process.onError((error) => { - reject(error); - }) - ); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === "EPIPE") { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error( - "The process exited prematurely." - ); - } - - reject(wrapCheckOutputWindow(error)); - } - } - ); - - return result.trim(); - } finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } + + constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { + super(() => this.dispose()); + } + + public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { + try { + const args: string[] = execArgs.slice() || []; // Snapshot since we modify it + args.push(connectionString); + + if (isEmulator) { + // Without these the connection will fail due to the self-signed DocDB certificate + if (args.indexOf("--ssl") < 0) { + args.push("--ssl"); + } + if (args.indexOf("--sslAllowInvalidCertificates") < 0) { + args.push("--sslAllowInvalidCertificates"); + } + } + + const process: InteractiveChildProcess = await InteractiveChildProcess.create({ + outputChannel: outputChannel, + command: execPath, + args, + outputFilterSearch: sentinelRegex, + outputFilterReplace: '' + }); + const shell: MongoShell = new MongoShell(process, timeoutSeconds); + + // Try writing an empty script to verify the process is running correctly and allow us + // to catch any errors related to the start-up of the process before trying to write to it. + await shell.executeScript(""); + + // Configure the batch size + await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); + + return shell; + } catch (error) { + throw wrapCheckOutputWindow(error); + } + } + + public dispose(): void { + this._process.kill(); + } + + public async useDatabase(database: string): Promise { + return await this.executeScript(`use ${database}`); + } + + public async executeScript(script: string): Promise { + script = convertToSingleLine(script); + + let stdOut = ""; + const sentinel = createSentinel(); + + const disposables: vscode.Disposable[] = []; + try { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + const result = await new Promise(async (resolve, reject) => { + try { + startScriptTimeout(this._timeoutSeconds, reject); + + // Hook up events + disposables.push( + this._process.onStdOut(text => { + stdOut += text; + // eslint-disable-next-line prefer-const + let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); + if (removed) { + // The sentinel was found, which means we are done. + + // Change the "type 'it' for more" message to one that doesn't ask users to type anything, + // since we're not currently interactive like that. + // CONSIDER: Ideally we would allow users to click a button to iterate through more data, + // or even just do it for them + stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); + + resolve(stdOutNoSentinel); + } + })); + disposables.push( + this._process.onStdErr(text => { + // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. + // So consider this an error. + // (It's okay if we fire this multiple times, the first one wins.) + reject(wrapCheckOutputWindow(text.trim())); + })); + disposables.push( + this._process.onError(error => { + reject(error); + })); + + // Write the script to STDIN + if (script) { + this._process.writeLine(script); + } + + // Mark end of result by sending the sentinel wrapped in quotes so the console will spit + // it back out as a string value after it's done processing the script + const quotedSentinel = `"${sentinel}"`; + this._process.writeLine(quotedSentinel); // (Don't display the sentinel) + + } catch (error) { + // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it + + if ((<{ code?: string }>error).code === 'EPIPE') { + // Give a chance for start-up errors to show up before rejecting with this more general error message + await delay(500); + // eslint-disable-next-line no-ex-assign + error = new Error("The process exited prematurely."); + } + + reject(wrapCheckOutputWindow(error)); + } + }); + + return result.trim(); + } + finally { + // Dispose event handlers + for (const d of disposables) { + d.dispose(); + } + } + } } -function startScriptTimeout( - timeoutSeconds: number | 0, - reject: (err: unknown) => void -): void { - if (timeoutSeconds > 0) { - setTimeout(() => { - reject(timeoutMessage); - }, timeoutSeconds * 1000); - } +function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { + if (timeoutSeconds > 0) { + setTimeout( + () => { + reject(timeoutMessage); + }, + timeoutSeconds * 1000); + } } function convertToSingleLine(script: string): string { - return script - .split(os.EOL) - .map((line) => line.trim()) - .join(""); + return script.split(os.EOL) + .map(line => line.trim()) + .join(''); + } -function removeSentinel( - text: string, - sentinel: string -): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } +function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { + const index = text.indexOf(sentinel); + if (index >= 0) { + return { text: text.slice(0, index), removed: true }; + } else { + return { text, removed: false }; + } } async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); } function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = - "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) - ? error - : wrapError(error, checkOutputMsg); + const checkOutputMsg = "The output window may contain additional information."; + return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); } diff --git a/Source/mongo/connectToMongoClient.ts b/Source/mongo/connectToMongoClient.ts index e2fe8d5d1..88aa2df17 100644 --- a/Source/mongo/connectToMongoClient.ts +++ b/Source/mongo/connectToMongoClient.ts @@ -3,58 +3,47 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MongoClient, MongoClientOptions } from "mongodb"; -import { emulatorPassword, Links } from "../constants"; - -export async function connectToMongoClient( - connectionString: string, - appName: string -): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true, - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string; name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if ( - message && - /ECONNREFUSED/.test(message) && - /(localhost|127\.0\.0\.1)/.test(message) - ) { - throw new MongoConnectError(); - } - - throw error; - } +import { MongoClient, MongoClientOptions } from 'mongodb'; +import { emulatorPassword, Links } from '../constants'; + +export async function connectToMongoClient(connectionString: string, appName: string): Promise { + // appname appears to be the correct equivalent to user-agent for mongo + const options: MongoClientOptions = { + // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string + appName: `@${appName}@`, + // https://github.com/lmammino/mongo-uri-builder/issues/2 + useNewUrlParser: true, + useUnifiedTopology: true + }; + + if (isCosmosEmulatorConnectionString(connectionString)) { + // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 + options.tlsAllowInvalidCertificates = true; + } + + try { + return await MongoClient.connect(connectionString, options); + } catch (err) { + // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info + const error = <{ message?: string, name?: string }>err; + const message = error && error.message; + + // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" + // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" + if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { + throw new MongoConnectError(); + } + + throw error; + } } export class MongoConnectError extends Error { - constructor() { - super( - `Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.` - ); - } + constructor() { + super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); + } } -export function isCosmosEmulatorConnectionString( - connectionString: string -): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); +export function isCosmosEmulatorConnectionString(connectionString: string): boolean { + return connectionString.includes(encodeURIComponent(emulatorPassword)); } diff --git a/Source/mongo/errorListeners.ts b/Source/mongo/errorListeners.ts index 00d510cd5..ea582d544 100644 --- a/Source/mongo/errorListeners.ts +++ b/Source/mongo/errorListeners.ts @@ -3,65 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRErrorListener } from "antlr4ts/ANTLRErrorListener"; -import { RecognitionException } from "antlr4ts/RecognitionException"; -import { Recognizer } from "antlr4ts/Recognizer"; -import { Token } from "antlr4ts/Token"; +import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; +import { RecognitionException } from 'antlr4ts/RecognitionException'; +import { Recognizer } from 'antlr4ts/Recognizer'; +import { Token } from 'antlr4ts/Token'; import * as vscode from "vscode"; -import { ErrorDescription } from "./MongoCommand"; +import { ErrorDescription } from './MongoCommand'; export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; - public get errors(): ErrorDescription[] { - return this._errors; - } + public get errors(): ErrorDescription[] { + return this._errors; + } - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined - ): void { - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: Token | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined): void { - const error: ErrorDescription = { - message: msg, - range: range, - exception: e, - }; - this._errors.push(error); - } + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); + + const error: ErrorDescription = { + message: msg, + range: range, + exception: e + }; + this._errors.push(error); + } } export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; + + public get errors(): ErrorDescription[] { + return this._errors; + } - public get errors(): ErrorDescription[] { - return this._errors; - } + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: number | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined): void { - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined - ): void { - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const error: ErrorDescription = { - message: msg, - range: range, - exception: e, - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e + }; + this._errors.push(error); + } } diff --git a/Source/mongo/grammar/mongoLexer.ts b/Source/mongo/grammar/mongoLexer.ts index 47b461a6f..3b6cbbdd0 100644 --- a/Source/mongo/grammar/mongoLexer.ts +++ b/Source/mongo/grammar/mongoLexer.ts @@ -9,312 +9,239 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from "antlr4ts/atn/ATN"; -import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; -import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; -import { CharStream } from "antlr4ts/CharStream"; -import { NotNull, Override } from "antlr4ts/Decorators"; -import { Lexer } from "antlr4ts/Lexer"; -import * as Utils from "antlr4ts/misc/Utils"; -import { RuleContext } from "antlr4ts/RuleContext"; -import { Vocabulary } from "antlr4ts/Vocabulary"; -import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +import { ATN } from 'antlr4ts/atn/ATN'; +import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; +import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; +import { CharStream } from 'antlr4ts/CharStream'; +import { NotNull, Override } from 'antlr4ts/Decorators'; +import { Lexer } from 'antlr4ts/Lexer'; +import * as Utils from 'antlr4ts/misc/Utils'; +import { RuleContext } from 'antlr4ts/RuleContext'; +import { Vocabulary } from 'antlr4ts/Vocabulary'; +import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = ["DEFAULT_MODE"]; - - public static readonly ruleNames: string[] = [ - "T__0", - "T__1", - "T__2", - "T__3", - "T__4", - "T__5", - "T__6", - "T__7", - "RegexLiteral", - "RegexFlag", - "SingleLineComment", - "MultiLineComment", - "StringLiteral", - "NullLiteral", - "BooleanLiteral", - "NumericLiteral", - "DecimalLiteral", - "LineTerminator", - "SEMICOLON", - "DOT", - "DB", - "IDENTIFIER", - "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", - "STRING_ESCAPE", - "DecimalIntegerLiteral", - "ExponentPart", - "DecimalDigit", - "WHITESPACE", - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, - "'('", - "','", - "')'", - "'{'", - "'}'", - "'['", - "']'", - "':'", - undefined, - undefined, - undefined, - undefined, - "'null'", - undefined, - undefined, - undefined, - undefined, - "';'", - "'.'", - "'db'", - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - "RegexLiteral", - "SingleLineComment", - "MultiLineComment", - "StringLiteral", - "NullLiteral", - "BooleanLiteral", - "NumericLiteral", - "DecimalLiteral", - "LineTerminator", - "SEMICOLON", - "DOT", - "DB", - "IDENTIFIER", - "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", - "WHITESPACE", - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( - mongoLexer._LITERAL_NAMES, - mongoLexer._SYMBOLIC_NAMES, - [] - ); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - private isExternalIdentifierText(text) { - return text === "db"; - } - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - @Override - public get grammarFileName(): string { - return "mongo.g4"; - } - @Override - public get ruleNames(): string[] { - return mongoLexer.ruleNames; - } - - @Override - public get serializedATN(): string { - return mongoLexer._serializedATN; - } - - @Override - public get modeNames(): string[] { - return mongoLexer.modeNames; - } - - @Override - public sempred( - _localctx: RuleContext, - ruleIndex: number, - predIndex: number - ): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred( - _localctx: RuleContext, - predIndex: number - ): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text); - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - 'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - 'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - '\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize( - Utils.toCharArray(mongoLexer._serializedATN) - ); - } +export class mongoLexer extends Lexer { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly modeNames: string[] = [ + "DEFAULT_MODE" + ]; + + public static readonly ruleNames: string[] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", + "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", + "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", + "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", + "ExponentPart", "DecimalDigit", "WHITESPACE" + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, + undefined, undefined, undefined, "'null'", undefined, undefined, undefined, + undefined, "';'", "'.'", "'db'" + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", + "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", + "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoLexer.VOCABULARY; + } + + + private isExternalIdentifierText(text) { + return text === 'db'; + } + + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(mongoLexer._ATN, this); + } + + @Override + public get grammarFileName(): string { return "mongo.g4"; } + + @Override + public get ruleNames(): string[] { return mongoLexer.ruleNames; } + + @Override + public get serializedATN(): string { return mongoLexer._serializedATN; } + + @Override + public get modeNames(): string[] { return mongoLexer.modeNames; } + + @Override + public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 21: + return this.IDENTIFIER_sempred(_localctx, predIndex); + } + return true; + } + private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { + switch (predIndex) { + case 0: + return !this.isExternalIdentifierText(this.text) + ; + } + return true; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + + "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + + "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + + "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + + "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + + "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + + "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + + "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + + "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + + "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + + "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + + "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + + "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + + "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + + "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + + "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + + "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + + "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + + "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + + "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + + "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + + "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + + "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + + "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + + "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + + "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + + "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + + "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + + "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + + "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + + "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + + "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + + "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + + "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + + "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + + "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + + "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + + "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + + ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + + "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + + "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + + "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + + "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + + "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + + "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + + "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + + "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + + "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + + "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + + "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + + "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + + "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + + "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + + "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + + "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + + "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + + "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + + "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + + "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + + "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + + "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + + "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + + "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + + "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + + "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + + "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + + "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + + "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + + "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + + "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + + "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + + "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + + "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + + "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + + "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + + "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + + "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + + "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + + "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + + "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + + "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + + "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + + "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + + "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + + "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + + "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + + "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + + "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + + "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + + "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + + "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + + "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + + "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + + "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + + "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + + "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + + "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + + "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + + "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + + "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + + "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + + "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + + "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + + "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + + "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + + "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + + "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + + "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + + "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + + "\x04\x02\x03\x02\b\x02\x02"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoLexer.__ATN) { + mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); + } + + return mongoLexer.__ATN; + } - return mongoLexer.__ATN; - } } + diff --git a/Source/mongo/grammar/mongoListener.ts b/Source/mongo/grammar/mongoListener.ts index d1d8ffac8..43514f500 100644 --- a/Source/mongo/grammar/mongoListener.ts +++ b/Source/mongo/grammar/mongoListener.ts @@ -1,30 +1,17 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { - ArgumentContext, - ArgumentsContext, - ArrayLiteralContext, - CollectionContext, - CommandContext, - CommandsContext, - CommentContext, - ElementListContext, - EmptyCommandContext, - FunctionCallContext, - LiteralContext, - MongoCommandsContext, - ObjectLiteralContext, - PropertyAssignmentContext, - PropertyNameAndValueListContext, - PropertyNameContext, - PropertyValueContext, -} from "./mongoParser"; + + +import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; +import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; + + /** * This interface defines a complete listener for a parse tree produced by @@ -156,16 +143,12 @@ export interface mongoListener extends ParseTreeListener { * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - enterPropertyNameAndValueList?: ( - ctx: PropertyNameAndValueListContext - ) => void; + enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; /** * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - exitPropertyNameAndValueList?: ( - ctx: PropertyNameAndValueListContext - ) => void; + exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; /** * Enter a parse tree produced by `mongoParser.propertyAssignment`. @@ -222,3 +205,4 @@ export interface mongoListener extends ParseTreeListener { */ exitComment?: (ctx: CommentContext) => void; } + diff --git a/Source/mongo/grammar/mongoParser.ts b/Source/mongo/grammar/mongoParser.ts index f08e3ff51..c1d38f4d0 100644 --- a/Source/mongo/grammar/mongoParser.ts +++ b/Source/mongo/grammar/mongoParser.ts @@ -9,1650 +9,1458 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from "antlr4ts/atn/ATN"; -import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; -import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; -import { NotNull, Override } from "antlr4ts/Decorators"; -import * as Utils from "antlr4ts/misc/Utils"; -import { NoViableAltException } from "antlr4ts/NoViableAltException"; -import { Parser } from "antlr4ts/Parser"; -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { RecognitionException } from "antlr4ts/RecognitionException"; -import { RuleVersion } from "antlr4ts/RuleVersion"; -import { Token } from "antlr4ts/Token"; -import { TokenStream } from "antlr4ts/TokenStream"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Vocabulary } from "antlr4ts/Vocabulary"; -import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; -import { mongoListener } from "./mongoListener"; -import { mongoVisitor } from "./mongoVisitor"; +import { ATN } from 'antlr4ts/atn/ATN'; +import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; +import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; +import { NotNull, Override } from 'antlr4ts/Decorators'; +import * as Utils from 'antlr4ts/misc/Utils'; +import { NoViableAltException } from 'antlr4ts/NoViableAltException'; +import { Parser } from 'antlr4ts/Parser'; +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { RecognitionException } from 'antlr4ts/RecognitionException'; +import { RuleVersion } from 'antlr4ts/RuleVersion'; +import { Token } from 'antlr4ts/Token'; +import { TokenStream } from 'antlr4ts/TokenStream'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { Vocabulary } from 'antlr4ts/Vocabulary'; +import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; +import { mongoListener } from './mongoListener'; +import { mongoVisitor } from './mongoVisitor'; + + + export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", - "commands", - "command", - "emptyCommand", - "collection", - "functionCall", - "arguments", - "argument", - "objectLiteral", - "arrayLiteral", - "elementList", - "propertyNameAndValueList", - "propertyAssignment", - "propertyValue", - "literal", - "propertyName", - "comment", - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, - "'('", - "','", - "')'", - "'{'", - "'}'", - "'['", - "']'", - "':'", - undefined, - undefined, - undefined, - undefined, - "'null'", - undefined, - undefined, - undefined, - undefined, - "';'", - "'.'", - "'db'", - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - "RegexLiteral", - "SingleLineComment", - "MultiLineComment", - "StringLiteral", - "NullLiteral", - "BooleanLiteral", - "NumericLiteral", - "DecimalLiteral", - "LineTerminator", - "SEMICOLON", - "DOT", - "DB", - "IDENTIFIER", - "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", - "WHITESPACE", - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( - mongoParser._LITERAL_NAMES, - mongoParser._SYMBOLIC_NAMES, - [] - ); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { - return "mongo.g4"; - } - - @Override - public get ruleNames(): string[] { - return mongoParser.ruleNames; - } - - @Override - public get serializedATN(): string { - return mongoParser._serializedATN; - } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.SingleLineComment) | - (1 << mongoParser.MultiLineComment) | - (1 << mongoParser.SEMICOLON) | - (1 << mongoParser.DB))) !== - 0 - ) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch ( - this.interpreter.adaptivePredict(this._input, 2, this._ctx) - ) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch ( - this.interpreter.adaptivePredict(this._input, 4, this._ctx) - ) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 5, - this._ctx - ); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 5, - this._ctx - ); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.T__3) | - (1 << mongoParser.T__5) | - (1 << mongoParser.RegexLiteral) | - (1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral) | - (1 << mongoParser.NumericLiteral))) !== - 0 - ) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - _la === mongoParser.StringLiteral || - _la === mongoParser.IDENTIFIER - ) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.T__3) | - (1 << mongoParser.T__5) | - (1 << mongoParser.RegexLiteral) | - (1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral) | - (1 << mongoParser.NumericLiteral) | - (1 << mongoParser.IDENTIFIER))) !== - 0 - ) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = - new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule( - _localctx, - 22, - mongoParser.RULE_propertyNameAndValueList - ); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 13, - this._ctx - ); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict( - this._input, - 13, - this._ctx - ); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = - new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if ( - !( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral))) !== - 0 - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if ( - !( - _la === mongoParser.StringLiteral || - _la === mongoParser.IDENTIFIER - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext( - this._ctx, - this.state - ); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if ( - !( - _la === mongoParser.SingleLineComment || - _la === mongoParser.MultiLineComment - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - '\x1C\x02\x1E\x02 \x02"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17' + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - '\x02\x02"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03' + - "\x03\x02\x02\x02'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize( - Utils.toCharArray(mongoParser._serializedATN) - ); - } - - return mongoParser.__ATN; - } + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly RULE_mongoCommands = 0; + public static readonly RULE_commands = 1; + public static readonly RULE_command = 2; + public static readonly RULE_emptyCommand = 3; + public static readonly RULE_collection = 4; + public static readonly RULE_functionCall = 5; + public static readonly RULE_arguments = 6; + public static readonly RULE_argument = 7; + public static readonly RULE_objectLiteral = 8; + public static readonly RULE_arrayLiteral = 9; + public static readonly RULE_elementList = 10; + public static readonly RULE_propertyNameAndValueList = 11; + public static readonly RULE_propertyAssignment = 12; + public static readonly RULE_propertyValue = 13; + public static readonly RULE_literal = 14; + public static readonly RULE_propertyName = 15; + public static readonly RULE_comment = 16; + public static readonly ruleNames: string[] = [ + "mongoCommands", "commands", "command", "emptyCommand", "collection", + "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", + "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", + "literal", "propertyName", "comment" + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, + undefined, undefined, undefined, "'null'", undefined, undefined, undefined, + undefined, "';'", "'.'", "'db'" + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", + "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", + "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoParser.VOCABULARY; + } + + @Override + public get grammarFileName(): string { return "mongo.g4"; } + + @Override + public get ruleNames(): string[] { return mongoParser.ruleNames; } + + @Override + public get serializedATN(): string { return mongoParser._serializedATN; } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(mongoParser._ATN, this); + } + @RuleVersion(0) + public mongoCommands(): MongoCommandsContext { + const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); + this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 34; + this.commands(); + this.state = 35; + this.match(mongoParser.EOF); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public commands(): CommandsContext { + const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); + this.enterRule(_localctx, 2, mongoParser.RULE_commands); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 42; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { + { + this.state = 40; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.DB: + { + this.state = 37; + this.command(); + } + break; + case mongoParser.SEMICOLON: + { + this.state = 38; + this.emptyCommand(); + } + break; + case mongoParser.SingleLineComment: + case mongoParser.MultiLineComment: + { + this.state = 39; + this.comment(); + } + break; + default: + throw new NoViableAltException(this); + } + } + this.state = 44; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public command(): CommandContext { + const _localctx: CommandContext = new CommandContext(this._ctx, this.state); + this.enterRule(_localctx, 4, mongoParser.RULE_command); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 45; + this.match(mongoParser.DB); + this.state = 48; + this._errHandler.sync(this); + switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { + case 1: + { + this.state = 46; + this.match(mongoParser.DOT); + this.state = 47; + this.collection(); + } + break; + } + this.state = 52; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 50; + this.match(mongoParser.DOT); + this.state = 51; + this.functionCall(); + } + } + this.state = 54; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la === mongoParser.DOT); + this.state = 57; + this._errHandler.sync(this); + switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { + case 1: + { + this.state = 56; + this.match(mongoParser.SEMICOLON); + } + break; + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public emptyCommand(): EmptyCommandContext { + const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 59; + this.match(mongoParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public collection(): CollectionContext { + const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); + this.enterRule(_localctx, 8, mongoParser.RULE_collection); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 61; + this.match(mongoParser.IDENTIFIER); + this.state = 66; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 62; + this.match(mongoParser.DOT); + this.state = 63; + this.match(mongoParser.IDENTIFIER); + } + } + } + this.state = 68; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public functionCall(): FunctionCallContext { + const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); + this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 69; + _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); + this.state = 70; + this.arguments(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arguments(): ArgumentsContext { + const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); + this.enterRule(_localctx, 12, mongoParser.RULE_arguments); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 72; + _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); + this.state = 81; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { + { + this.state = 73; + this.argument(); + this.state = 78; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 74; + this.match(mongoParser.T__1); + this.state = 75; + this.argument(); + } + } + this.state = 80; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + this.state = 83; + _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public argument(): ArgumentContext { + const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); + this.enterRule(_localctx, 14, mongoParser.RULE_argument); + try { + this.state = 88; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 85; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 86; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 87; + this.arrayLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public objectLiteral(): ObjectLiteralContext { + const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); + this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 90; + this.match(mongoParser.T__3); + this.state = 92; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { + { + this.state = 91; + this.propertyNameAndValueList(); + } + } + + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.T__1) { + { + this.state = 94; + this.match(mongoParser.T__1); + } + } + + this.state = 97; + this.match(mongoParser.T__4); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arrayLiteral(): ArrayLiteralContext { + const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); + this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 99; + this.match(mongoParser.T__5); + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { + { + this.state = 100; + this.elementList(); + } + } + + this.state = 103; + this.match(mongoParser.T__6); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public elementList(): ElementListContext { + const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); + this.enterRule(_localctx, 20, mongoParser.RULE_elementList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 105; + this.propertyValue(); + this.state = 110; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 106; + this.match(mongoParser.T__1); + this.state = 107; + this.propertyValue(); + } + } + this.state = 112; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyNameAndValueList(): PropertyNameAndValueListContext { + const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); + this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 113; + this.propertyAssignment(); + this.state = 118; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 114; + this.match(mongoParser.T__1); + this.state = 115; + this.propertyAssignment(); + } + } + } + this.state = 120; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyAssignment(): PropertyAssignmentContext { + const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); + this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 121; + this.propertyName(); + this.state = 122; + this.match(mongoParser.T__7); + this.state = 123; + this.propertyValue(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyValue(): PropertyValueContext { + const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); + this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); + try { + this.state = 129; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 125; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 126; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 127; + this.arrayLiteral(); + } + break; + case mongoParser.IDENTIFIER: + this.enterOuterAlt(_localctx, 4); + { + this.state = 128; + this.functionCall(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public literal(): LiteralContext { + const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); + this.enterRule(_localctx, 28, mongoParser.RULE_literal); + let _la: number; + try { + this.state = 134; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 131; + _la = this._input.LA(1); + if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + break; + case mongoParser.RegexLiteral: + this.enterOuterAlt(_localctx, 2); + { + this.state = 132; + this.match(mongoParser.RegexLiteral); + } + break; + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 3); + { + this.state = 133; + this.match(mongoParser.NumericLiteral); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyName(): PropertyNameContext { + const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); + this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 136; + _la = this._input.LA(1); + if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public comment(): CommentContext { + const _localctx: CommentContext = new CommentContext(this._ctx, this.state); + this.enterRule(_localctx, 32, mongoParser.RULE_comment); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 138; + _la = this._input.LA(1); + if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + + "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + + "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + + "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + + "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + + "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + + "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + + "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + + "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + + "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + + "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + + "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + + "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + + "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + + "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + + "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + + "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + + "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + + "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + + "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + + ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + + "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + + "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + + "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + + "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + + "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + + "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + + "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + + "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + + "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + + "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + + "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + + "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + + "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + + "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + + "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + + "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + + "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + + "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + + "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + + "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + + "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + + "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + + "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + + "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + + "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + + "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + + "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + + "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + + "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + + "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + + "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoParser.__ATN) { + mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); + } + + return mongoParser.__ATN; + } + } export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { - return this.getToken(mongoParser.EOF, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_mongoCommands; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } + public commands(): CommandsContext { + return this.getRuleContext(0, CommandsContext); + } + public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterMongoCommands) listener.enterMongoCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitMongoCommands) listener.exitMongoCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); + else return visitor.visitChildren(this); + } } + export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand( - i?: number - ): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_commands; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } + public command(): CommandContext[]; + public command(i: number): CommandContext; + public command(i?: number): CommandContext | CommandContext[] { + if (i === undefined) { + return this.getRuleContexts(CommandContext); + } else { + return this.getRuleContext(i, CommandContext); + } + } + public emptyCommand(): EmptyCommandContext[]; + public emptyCommand(i: number): EmptyCommandContext; + public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { + if (i === undefined) { + return this.getRuleContexts(EmptyCommandContext); + } else { + return this.getRuleContext(i, EmptyCommandContext); + } + } + public comment(): CommentContext[]; + public comment(i: number): CommentContext; + public comment(i?: number): CommentContext | CommentContext[] { + if (i === undefined) { + return this.getRuleContexts(CommentContext); + } else { + return this.getRuleContext(i, CommentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommands) listener.enterCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommands) listener.exitCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommands) return visitor.visitCommands(this); + else return visitor.visitChildren(this); + } } + export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { - return this.getToken(mongoParser.DB, 0); - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall( - i?: number - ): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.SEMICOLON, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_command; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } + public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + public collection(): CollectionContext | undefined { + return this.tryGetRuleContext(0, CollectionContext); + } + public functionCall(): FunctionCallContext[]; + public functionCall(i: number): FunctionCallContext; + public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionCallContext); + } else { + return this.getRuleContext(i, FunctionCallContext); + } + } + public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_command; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommand) listener.enterCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommand) listener.exitCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommand) return visitor.visitCommand(this); + else return visitor.visitChildren(this); + } } + export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { - return this.getToken(mongoParser.SEMICOLON, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_emptyCommand; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } + public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); + else return visitor.visitChildren(this); + } } + export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_collection; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.IDENTIFIER); + } else { + return this.getToken(mongoParser.IDENTIFIER, i); + } + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCollection) listener.enterCollection(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCollection) listener.exitCollection(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCollection) return visitor.visitCollection(this); + else return visitor.visitChildren(this); + } } + export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { - return this.getToken(mongoParser.IDENTIFIER, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_functionCall; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } + public _FUNCTION_NAME: Token; + public arguments(): ArgumentsContext { + return this.getRuleContext(0, ArgumentsContext); + } + public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterFunctionCall) listener.enterFunctionCall(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitFunctionCall) listener.exitFunctionCall(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); + else return visitor.visitChildren(this); + } } + export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_arguments; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } + public _OPEN_PARENTHESIS: Token; + public _CLOSED_PARENTHESIS: Token; + public argument(): ArgumentContext[]; + public argument(i: number): ArgumentContext; + public argument(i?: number): ArgumentContext | ArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(ArgumentContext); + } else { + return this.getRuleContext(i, ArgumentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArguments) listener.enterArguments(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArguments) listener.exitArguments(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArguments) return visitor.visitArguments(this); + else return visitor.visitChildren(this); + } } + export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_argument; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArgument) listener.enterArgument(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArgument) listener.exitArgument(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArgument) return visitor.visitArgument(this); + else return visitor.visitChildren(this); + } } + export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): - | PropertyNameAndValueListContext - | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_objectLiteral; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } + public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { + return this.tryGetRuleContext(0, PropertyNameAndValueListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); + else return visitor.visitChildren(this); + } } + export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_arrayLiteral; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } + public elementList(): ElementListContext | undefined { + return this.tryGetRuleContext(0, ElementListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); + else return visitor.visitChildren(this); + } } + export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue( - i?: number - ): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_elementList; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } + public propertyValue(): PropertyValueContext[]; + public propertyValue(i: number): PropertyValueContext; + public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyValueContext); + } else { + return this.getRuleContext(i, PropertyValueContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterElementList) listener.enterElementList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitElementList) listener.exitElementList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitElementList) return visitor.visitElementList(this); + else return visitor.visitChildren(this); + } } + export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment( - i?: number - ): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyNameAndValueList; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) - listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) - listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) - return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } + public propertyAssignment(): PropertyAssignmentContext[]; + public propertyAssignment(i: number): PropertyAssignmentContext; + public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyAssignmentContext); + } else { + return this.getRuleContext(i, PropertyAssignmentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); + else return visitor.visitChildren(this); + } } + export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyAssignment; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) - listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) - listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) - return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } + public propertyName(): PropertyNameContext { + return this.getRuleContext(0, PropertyNameContext); + } + public propertyValue(): PropertyValueContext { + return this.getRuleContext(0, PropertyValueContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); + else return visitor.visitChildren(this); + } } + export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyValue; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + public functionCall(): FunctionCallContext | undefined { + return this.tryGetRuleContext(0, FunctionCallContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyValue) listener.enterPropertyValue(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyValue) listener.exitPropertyValue(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); + else return visitor.visitChildren(this); + } } + export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.NullLiteral, 0); - } - public BooleanLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.BooleanLiteral, 0); - } - public StringLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.StringLiteral, 0); - } - public RegexLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.RegexLiteral, 0); - } - public NumericLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.NumericLiteral, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_literal; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } + public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } + public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } + public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } + public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } + public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterLiteral) listener.enterLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitLiteral) listener.exitLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitLiteral) return visitor.visitLiteral(this); + else return visitor.visitChildren(this); + } } + export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.StringLiteral, 0); - } - public IDENTIFIER(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.IDENTIFIER, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyName; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } + public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } + public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyName) listener.enterPropertyName(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyName) listener.exitPropertyName(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyName) return visitor.visitPropertyName(this); + else return visitor.visitChildren(this); + } } + export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.SingleLineComment, 0); - } - public MultiLineComment(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.MultiLineComment, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_comment; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } + public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } + public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + + } + @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterComment) listener.enterComment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitComment) listener.exitComment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitComment) return visitor.visitComment(this); + else return visitor.visitChildren(this); + } } + + diff --git a/Source/mongo/grammar/mongoVisitor.ts b/Source/mongo/grammar/mongoVisitor.ts index 105184d2d..eb001a6e9 100644 --- a/Source/mongo/grammar/mongoVisitor.ts +++ b/Source/mongo/grammar/mongoVisitor.ts @@ -1,30 +1,17 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; -import { - ArgumentContext, - ArgumentsContext, - ArrayLiteralContext, - CollectionContext, - CommandContext, - CommandsContext, - CommentContext, - ElementListContext, - EmptyCommandContext, - FunctionCallContext, - LiteralContext, - MongoCommandsContext, - ObjectLiteralContext, - PropertyAssignmentContext, - PropertyNameAndValueListContext, - PropertyNameContext, - PropertyValueContext, -} from "./mongoParser"; + + +import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; +import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; + + /** * This interface defines a complete generic visitor for a parse tree produced @@ -116,9 +103,7 @@ export interface mongoVisitor extends ParseTreeVisitor { * @param ctx the parse tree * @return the visitor result */ - visitPropertyNameAndValueList?: ( - ctx: PropertyNameAndValueListContext - ) => Result; + visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; /** * Visit a parse tree produced by `mongoParser.propertyAssignment`. @@ -155,3 +140,4 @@ export interface mongoVisitor extends ParseTreeVisitor { */ visitComment?: (ctx: CommentContext) => Result; } + diff --git a/Source/mongo/grammar/visitors.ts b/Source/mongo/grammar/visitors.ts index 20e69315d..e1ba1b63d 100644 --- a/Source/mongo/grammar/visitors.ts +++ b/Source/mongo/grammar/visitors.ts @@ -3,88 +3,81 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ErrorNode } from "antlr4ts/tree/ErrorNode"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { - ArgumentContext, - ArgumentsContext, - CollectionContext, - CommandContext, - CommandsContext, - FunctionCallContext, - MongoCommandsContext, -} from "./mongoParser"; -import { mongoVisitor } from "./mongoVisitor"; +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; +import { mongoVisitor } from './mongoVisitor'; export class MongoVisitor implements mongoVisitor { - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount; - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return (null); - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } + + visitMongoCommands(ctx: MongoCommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommands(ctx: CommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommand(ctx: CommandContext): T { + return this.visitChildren(ctx); + } + + visitCollection(ctx: CollectionContext): T { + return this.visitChildren(ctx); + } + + visitFunctionCall(ctx: FunctionCallContext): T { + return this.visitChildren(ctx); + } + + visitArgument(ctx: ArgumentContext): T { + return this.visitChildren(ctx); + } + + visitArguments(ctx: ArgumentsContext): T { + return this.visitChildren(ctx); + } + + visit(tree: ParseTree): T { + return tree.accept(this); + } + + visitChildren(ctx: ParserRuleContext): T { + let result = this.defaultResult(ctx); + const n = ctx.childCount + for (let i = 0; i < n; i++) { + if (!this.shouldVisitNextChild(ctx, result)) { + break; + } + + const childNode = ctx.getChild(i); + const childResult = childNode.accept(this); + result = this.aggregateResult(result, childResult); + } + return result; + } + + visitTerminal(node: TerminalNode): T { + return this.defaultResult(node); + } + + visitErrorNode(node: ErrorNode): T { + return this.defaultResult(node); + } + + protected defaultResult(_node: ParseTree): T { + // grandfathered-in. Unclear why this is null instead of type T + return null; + } + + protected aggregateResult(aggregate: T, nextResult: T): T { + return !nextResult ? aggregate : nextResult; + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + shouldVisitNextChild(_node, _currentResult: T): boolean { + return true; + } } diff --git a/Source/mongo/languageClient.ts b/Source/mongo/languageClient.ts index 6f445423e..e4bd4aefd 100644 --- a/Source/mongo/languageClient.ts +++ b/Source/mongo/languageClient.ts @@ -2,81 +2,57 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; -import * as path from "path"; -import { - LanguageClient, - LanguageClientOptions, - ServerOptions, - TransportKind, -} from "vscode-languageclient"; -import * as nls from "vscode-nls"; -import { ext } from "../extensionVariables"; -import { IConnectionParams } from "./services/IConnectionParams"; +import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; +import * as path from 'path'; +import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; +import * as nls from 'vscode-nls'; +import { ext } from '../extensionVariables'; +import { IConnectionParams } from './services/IConnectionParams'; const localize = nls.loadMessageBundle(); export class MongoDBLanguageClient { - public client: LanguageClient; - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle - ? ext.context.asAbsolutePath( - path.join("out", "src", "mongo", "languageServer.js") - ) - : ext.context.asAbsolutePath( - path.join("dist", "mongo-languageServer.bundle.js") - ); - // The debug options for the server - const debugOptions = { execArgv: ["--nolazy", "--inspect=6005"] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { - module: serverModule, - transport: TransportKind.ipc, - options: debugOptions, - }, - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: "mongo", scheme: "file" }, - { language: "mongo", scheme: "untitled" }, - ], - }; - - // Create the language client and start the client. - this.client = new LanguageClient( - "mongo", - localize("mongo.server.name", "Mongo Language Server"), - serverOptions, - clientOptions - ); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect( - connectionString: string, - databaseName: string - ): Promise { - await this.client.sendRequest("connect", { - connectionString: connectionString, - databaseName: databaseName, - extensionUserAgent: appendExtensionUserAgent(), - }); - } - - public async disconnect(): Promise { - await this.client.sendRequest("disconnect"); - } + public client: LanguageClient; + + constructor() { + // The server is implemented in node + const serverModule = ext.ignoreBundle ? + ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : + ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); + // The debug options for the server + const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; + + // If the extension is launch in debug mode the debug server options are use + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for mongo javascript documents + documentSelector: [ + { language: 'mongo', scheme: 'file' }, + { language: 'mongo', scheme: 'untitled' } + ] + }; + + // Create the language client and start the client. + this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); + const disposable = this.client.start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + ext.context.subscriptions.push(disposable); + } + + public async connect(connectionString: string, databaseName: string): Promise { + await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); + } + + public async disconnect(): Promise { + await this.client.sendRequest('disconnect'); + } } diff --git a/Source/mongo/languageServer.ts b/Source/mongo/languageServer.ts index 8c76686f6..d5d6ec484 100644 --- a/Source/mongo/languageServer.ts +++ b/Source/mongo/languageServer.ts @@ -2,8 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from "vscode-languageserver"; -import { LanguageService } from "./services/languageService"; +import { createConnection, IConnection } from 'vscode-languageserver'; +import { LanguageService } from './services/languageService'; // // diff --git a/Source/mongo/mongoConnectionStrings.ts b/Source/mongo/mongoConnectionStrings.ts index 89d04ed30..5f73db484 100644 --- a/Source/mongo/mongoConnectionStrings.ts +++ b/Source/mongo/mongoConnectionStrings.ts @@ -3,11 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - appendExtensionUserAgent, - IParsedError, - parseError, -} from "@microsoft/vscode-azext-utils"; +import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; import { MongoClient } from "mongodb"; import { testDb } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; @@ -25,118 +21,84 @@ import { connectToMongoClient } from "./connectToMongoClient"; // mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] // [database] -const parsePrefix = "([a-zA-Z]+://[^/]*)"; -const parseDatabaseName = "/?([^/?]+)?"; +const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; +const parseDatabaseName = '\/?([^/?]+)?'; const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); -export function getDatabaseNameFromConnectionString( - connectionString: string -): string | undefined { - try { - const [, , databaseName] = nonNullValue( - connectionString.match(mongoConnectionStringRegExp), - "databaseNameMatch" - ); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } +export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { + try { + const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); + return databaseName; + } catch (error) { + // Shouldn't happen, but ignore if does + } - return undefined; + return undefined; } -export function addDatabaseToAccountConnectionString( - connectionString: string, - databaseName: string -): string { - try { - return connectionString.replace( - mongoConnectionStringRegExp, - `$1\/${encodeURIComponent(databaseName)}` - ); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } +export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { + try { + return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); + } catch (error) { + // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it + return connectionString; + } } -export async function parseMongoConnectionString( - connectionString: string -): Promise { - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient( - connectionString, - appendExtensionUserAgent() - ); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient( - connectionString, - appendExtensionUserAgent() - ); - } else { - throw error; - } - } +export async function parseMongoConnectionString(connectionString: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; + let mongoClient: MongoClient; + try { + mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); + } catch (error) { + const parsedError: IParsedError = parseError(error); + if (parsedError.message.match(/unescaped/i)) { + // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 + connectionString = encodeMongoConnectionString(connectionString); + mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); + } else { + throw error; + } + } - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = - serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = - serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const serverConfig: any = mongoClient.db(testDb).serverConfig; - return new ParsedMongoConnectionString( - connectionString, - host, - port, - getDatabaseNameFromConnectionString(connectionString) - ); + // get the first connection string from the servers list + // this may not be best solution, but the connection (below) gives + // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) + // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; + + return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); } export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - constructor( - connectionString: string, - hostName: string, - port: string, - databaseName: string | undefined - ) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } + constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { + super(connectionString, databaseName); + this.hostName = hostName; + this.port = port; + } } /** * Encodes the username and password in the given Mongo DB connection string. */ export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match( - /^(.*):\/\/(.*):(.*)@(.*)/ - ); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent( - username - )}:${encodeURIComponent(password)}@${hostAndQuery}`; - } + const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); + if (matches) { + const prefix: string = matches[1]; + const username: string = matches[2]; + const password: string = matches[3]; + const hostAndQuery: string = matches[4]; + connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; + } - return connectionString; + return connectionString; } diff --git a/Source/mongo/registerMongoCommands.ts b/Source/mongo/registerMongoCommands.ts index 713ff9104..2dc36477a 100644 --- a/Source/mongo/registerMongoCommands.ts +++ b/Source/mongo/registerMongoCommands.ts @@ -3,28 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, - IErrorHandlerContext, - ITreeItemPickerContext, - registerCommandWithTreeNodeUnwrapping, - registerErrorHandler, - registerEvent, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { Experience, MongoExperience } from "../AzureDBExperiences"; +import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; +import * as vscode from 'vscode'; +import { Experience, MongoExperience } from '../AzureDBExperiences'; import { cosmosMongoFilter } from "../constants"; import { ext } from "../extensionVariables"; -import * as vscodeUtil from "../utils/vscodeUtils"; -import { MongoConnectError } from "./connectToMongoClient"; +import * as vscodeUtil from '../utils/vscodeUtils'; +import { MongoConnectError } from './connectToMongoClient'; import { MongoDBLanguageClient } from "./languageClient"; -import { - executeAllCommandsFromActiveEditor, - executeCommandFromActiveEditor, - getAllErrorsFromTextDocument, -} from "./MongoScrapbook"; +import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; import { setConnectedNode } from "./setConnectedNode"; import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; @@ -32,328 +19,205 @@ import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; -const connectedMongoKey: string = "ms-azuretools.vscode-cosmosdb.connectedDB"; +const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = "mongo"; +const mongoLanguageId: string = 'mongo'; export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push( - vscode.languages.registerCodeLensProvider( - mongoLanguageId, - ext.mongoCodeLensProvider - ) - ); - - diagnosticsCollection = - vscode.languages.createDiagnosticCollection("cosmosDB.mongo"); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createMongoDatabase", - createMongoDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createMongoCollection", - createMongoCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.createMongoDocument", - async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo( - context, - MongoCollectionTreeItem.contextValue - ); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand( - "cosmosDB.openDocument", - documentNode - ); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.connectMongoDB", - async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { - defaultExperience?: Experience; - } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo( - experienceContext, - MongoDatabaseTreeItem.contextValue - ); - } - - const oldNodeId: string | undefined = - ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect( - node.connectionString, - node.databaseName - ); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - oldNodeId, - context - ); - if (oldNode) { - await oldNode.refresh(context); - } - } - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteMongoDB", - deleteMongoDB - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteMongoCollection", - deleteMongoCollection - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.deleteMongoDocument", - async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo( - context, - MongoDocumentTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.openCollection", - async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo( - context, - MongoCollectionTreeItem.contextValue - ); - } - await ext.fileSystem.showTextDocument(node); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.launchMongoShell", - launchMongoShell - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.newMongoScrapbook", - async () => await vscodeUtil.showNewFile("", "Scrapbook", ".mongo") - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.executeMongoCommand", - async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - } - ); - registerCommandWithTreeNodeUnwrapping( - "cosmosDB.executeAllMongoCommands", - async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - } - ); + ext.mongoLanguageClient = new MongoDBLanguageClient(); + + ext.mongoCodeLensProvider = new MongoCodeLensProvider(); + ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); + + diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); + ext.context.subscriptions.push(diagnosticsCollection); + + setUpErrorReporting(); + + const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); + + registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo(context, MongoCollectionTreeItem.contextValue); + } + const documentNode = await node.createChild(context); + await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { + if (!node) { + // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 + const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; + node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); + } + + const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; + await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); + void ext.context.globalState.update(connectedMongoKey, node.fullId); + setConnectedNode(node); + await node.refresh(context); + + if (oldNodeId) { + // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); + if (oldNode) { + await oldNode.refresh(context); + } + } + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); + registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo(context, MongoDocumentTreeItem.contextValue); + } + await node.deleteTreeItem(context); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo(context, MongoCollectionTreeItem.contextValue); + } + await ext.fileSystem.showTextDocument(node); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); + registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); + registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { + await loadPersistedMongoDBTask; + await executeCommandFromActiveEditor(context, position); + }); + registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { + await loadPersistedMongoDBTask; + await executeAllCommandsFromActiveEditor(context); + }); } async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling( - "cosmosDB.loadPersistedMongoDB", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = "true"; - - try { - const persistedNodeId: string | undefined = - ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = - await ext.rgApi.appResourceTree.findTreeItem( - persistedNodeId, - context - ); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand( - "cosmosDB.connectMongoDB", - persistedNode - ); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - } - ); + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = 'true'; + + try { + const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); + if (persistedNodeId) { + const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); + if (persistedNode) { + await ext.mongoLanguageClient.client.onReady(); + await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedMongoDB) { + ext.mongoCodeLensProvider.setConnectedDatabase(undefined); + } + } + }); } function launchMongoShell(): void { - const terminal: vscode.Terminal = - vscode.window.createTerminal("Mongo Shell"); - terminal.sendText(`mongo`); - terminal.show(); + const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); + terminal.sendText(`mongo`); + terminal.show(); } function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook( - context, - vscode.window.activeTextEditor?.document - ); - } - ); - - // Update errors when document opened/changed - registerEvent( - "vscode.workspace.onDidOpenTextDocument", - vscode.workspace.onDidOpenTextDocument, - updateErrorsInScrapbook - ); - registerEvent( - "vscode.workspace.onDidChangeTextDocument", - vscode.workspace.onDidChangeTextDocument, - async ( - context: IActionContext, - event: vscode.TextDocumentChangeEvent - ) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - } - ); - registerEvent( - "vscode.workspace.onDidCloseTextDocument", - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - } - ); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); + // Update errors immediately in case a scrapbook is already open + void callWithTelemetryAndErrorHandling( + "initialUpdateErrorsInActiveDocument", + async (context: IActionContext) => { + updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); + }); + + // Update errors when document opened/changed + registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); + registerEvent( + 'vscode.workspace.onDidChangeTextDocument', + vscode.workspace.onDidChangeTextDocument, + async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { + // Always suppress success telemetry - event happens on every keystroke + context.telemetry.suppressIfSuccessful = true; + + updateErrorsInScrapbook(context, event.document); + }); + registerEvent( + 'vscode.workspace.onDidCloseTextDocument', + vscode.workspace.onDidCloseTextDocument, + async (context: IActionContext, document: vscode.TextDocument) => { + // Remove errors when closed + if (document?.languageId === mongoLanguageId) { + diagnosticsCollection.set(document.uri, []); + } else { + context.telemetry.suppressIfSuccessful = true; + } + }); + + registerErrorHandler((context: IErrorHandlerContext) => { + if (context.error instanceof MongoConnectError) { + context.errorHandling.suppressReportIssue = true; + } + }); } -function updateErrorsInScrapbook( - context: IActionContext, - document: vscode.TextDocument | undefined -): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } +function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { + if (document?.languageId === mongoLanguageId) { + const errors = getAllErrorsFromTextDocument(document); + diagnosticsCollection.set(document.uri, errors); + } else { + context.telemetry.suppressIfSuccessful = true; + } } -export async function createMongoDatabase( - context: IActionContext, - node?: MongoAccountTreeItem -): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); +export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { + if (!node) { + node = await pickMongo(context); + } + const databaseNode = await node.createChild(context); + await databaseNode.createChild(context); - await vscode.commands.executeCommand( - "cosmosDB.connectMongoDB", - databaseNode - ); + await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); } -export async function createMongoCollection( - context: IActionContext, - node?: MongoDatabaseTreeItem -): Promise { - if (!node) { - node = await pickMongo( - context, - MongoDatabaseTreeItem.contextValue - ); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand( - "cosmosDB.connectMongoDB", - collectionNode.parent - ); +export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { + if (!node) { + node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); + } + const collectionNode = await node.createChild(context); + await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); } -export async function deleteMongoDB( - context: IActionContext, - node?: MongoDatabaseTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo( - context, - MongoDatabaseTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } +export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); + } + await node.deleteTreeItem(context); + if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { + setConnectedNode(undefined); + void ext.context.globalState.update(connectedMongoKey, undefined); + // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 + void ext.mongoLanguageClient.disconnect(); + } } -export async function deleteMongoCollection( - context: IActionContext, - node?: MongoCollectionTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo( - context, - MongoCollectionTreeItem.contextValue - ); - } - await node.deleteTreeItem(context); +export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo(context, MongoCollectionTreeItem.contextValue); + } + await node.deleteTreeItem(context); } -async function pickMongo( - context: IActionContext, - expectedContextValue?: string | RegExp | (string | RegExp)[] -): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [cosmosMongoFilter], - expectedChildContextValue: expectedContextValue, - }); +async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter + ], + expectedChildContextValue: expectedContextValue + }); } diff --git a/Source/mongo/services/IConnectionParams.ts b/Source/mongo/services/IConnectionParams.ts index 55d2cc73a..eec39e4cf 100644 --- a/Source/mongo/services/IConnectionParams.ts +++ b/Source/mongo/services/IConnectionParams.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; + connectionString: string; + databaseName: string; + extensionUserAgent: string; } diff --git a/Source/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts index 01aaff56f..3407c50dd 100644 --- a/Source/mongo/services/MongoCodeLensProvider.ts +++ b/Source/mongo/services/MongoCodeLensProvider.ts @@ -3,89 +3,73 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = - new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): vscode.Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses( - document: vscode.TextDocument, - _token: vscode.CancellationToken - ): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling( - "mongo.provideCodeLenses", - (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { + return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: vscode.CodeLens[] = []; - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized - ? "Initializing..." - : isConnected - ? `Connected to ${database}` - : `Connect to a database`, - command: isInitialized && "cosmosDB.connectMongoDB", - }, - range: new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position(0, 0) - ), - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title: !isInitialized ? + 'Initializing...' : + isConnected ? + `Connected to ${database}` : + `Connect to a database`, + command: isInitialized && 'cosmosDB.connectMongoDB' + }, + range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) + }); - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: "cosmosDB.executeAllMongoCommands", - }, - range: new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position(0, 0) - ), - }); + if (isConnected) { + // Run all + lenses.push({ + command: { + title: "Execute All", + command: 'cosmosDB.executeAllMongoCommands' + }, + range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) + }); - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: "cosmosDB.executeMongoCommand", - arguments: [cmd.range.start], - }, - range: cmd.range, - }); - } - } + const commands = getAllCommandsFromTextDocument(document); + for (const cmd of commands) { + // run individual + lenses.push({ + command: { + title: "Execute", + command: 'cosmosDB.executeMongoCommand', + arguments: [cmd.range.start] + }, + range: cmd.range + }); + } + } - return lenses; - } - ); - } + return lenses; + }); + } } diff --git a/Source/mongo/services/completionItemProvider.ts b/Source/mongo/services/completionItemProvider.ts index 4abb71432..cba51890c 100644 --- a/Source/mongo/services/completionItemProvider.ts +++ b/Source/mongo/services/completionItemProvider.ts @@ -5,588 +5,435 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ErrorNode } from "antlr4ts/tree/ErrorNode"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Db } from "mongodb"; -import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; -import { - CompletionItem, - CompletionItemKind, - Position, - Range, -} from "vscode-languageserver"; -import { TextDocument } from "vscode-languageserver-textdocument"; -import { mongoLexer } from "./../grammar/mongoLexer"; -import * as mongoParser from "./../grammar/mongoParser"; -import { MongoVisitor } from "./../grammar/visitors"; -import { SchemaService } from "./schemaService"; - -export class CompletionItemsVisitor extends MongoVisitor< - Promise -> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands( - ctx: mongoParser.CommandsContext - ): Promise { - return this.thenable( - this.createDbKeywordCompletion(this.createRange(ctx)) - ); - } - - public visitEmptyCommand( - ctx: mongoParser.EmptyCommandContext - ): Promise { - return this.thenable( - this.createDbKeywordCompletion(this.createRangeAfter(ctx)) - ); - } - - public visitCommand( - ctx: mongoParser.CommandContext - ): Promise { - if (ctx.childCount === 0) { - return this.thenable( - this.createDbKeywordCompletion(this.createRange(ctx)) - ); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection( - ctx: mongoParser.CollectionContext - ): Promise { - return Promise.all([ - this.createCollectionCompletions(this.createRange(ctx)), - this.createDbFunctionCompletions(this.createRange(ctx)), - ]).then(([collectionCompletions, dbFunctionCompletions]) => [ - ...collectionCompletions, - ...dbFunctionCompletions, - ]); - } - - public visitFunctionCall( - ctx: mongoParser.FunctionCallContext - ): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments( - ctx: mongoParser.ArgumentsContext - ): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable( - this.createDbKeywordCompletion( - this.createRangeAfter(terminalNode) - ) - ); - } - return this.thenable(); - } - - public visitArgument( - ctx: mongoParser.ArgumentContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral( - ctx: mongoParser.ObjectLiteralContext - ): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if ( - [ - "find", - "findOne", - "findOneAndDelete", - "findOneAndUpdate", - "findOneAndReplace", - "deleteOne", - "deleteMany", - "remove", - ].indexOf(functionName) !== -1 - ) { - return this.getArgumentCompletionItems( - this.schemaService.queryDocumentUri(collectionName), - collectionName, - ctx - ); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral( - ctx: mongoParser.ArrayLiteralContext - ): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (["aggregate"].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems( - this.schemaService.aggregateDocumentUri(collectionName), - collectionName, - ctx - ); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList( - ctx: mongoParser.ElementListContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList( - ctx: mongoParser.PropertyNameAndValueListContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment( - ctx: mongoParser.PropertyAssignmentContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue( - ctx: mongoParser.PropertyValueContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName( - ctx: mongoParser.PropertyNameContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral( - ctx: mongoParser.LiteralContext - ): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems( - documentUri: string, - _collectionName: string, - ctx: ParserRuleContext - ): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create( - documentUri, - "json", - 1, - text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1) - ); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService - .doComplete( - document, - position, - this.jsonLanguageService.parseJSONDocument(document) - ) - .then((list) => { - return list!.items.map((item) => { - const startPositionOffset = document.offsetAt( - item.textEdit!.range.start - ); - const endPositionOffset = document.offsetAt( - item.textEdit!.range.end - ); - item.textEdit!.range = Range.create( - this.textDocument.positionAt( - startPositionOffset + contextOffset - ), - this.textDocument.positionAt( - contextOffset + endPositionOffset - ) - ); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if ( - previousNode && - previousNode instanceof TerminalNode && - previousNode.symbol.type === mongoLexer.DOT - ) { - previousNode = this.getPreviousNode(previousNode); - if ( - previousNode && - previousNode instanceof mongoParser.CollectionContext - ) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode( - node: TerminalNode - ): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable( - this.createDbKeywordCompletion(this.createRange(node)) - ); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable( - this.createDbKeywordCompletion(this.createRangeAfter(node)) - ); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([ - this.createCollectionCompletions( - this.createRangeAfter(node) - ), - this.createDbFunctionCompletions( - this.createRangeAfter(node) - ), - ]).then( - ([collectionCompletions, dbFunctionCompletions]) => [ - ...collectionCompletions, - ...dbFunctionCompletions, - ] - ); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions( - this.createRangeAfter(node) - ); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode( - previousNode - ); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children - .slice() - .reverse() - .filter( - (node) => - node instanceof TerminalNode && - node.symbol.stopIndex > -1 && - node.symbol.stopIndex < this.offset - )[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: "db", - range, - }, - kind: CompletionItemKind.Keyword, - label: "db", - }; - } - - private createDbFunctionCompletions( - range: Range - ): Promise { - return this.thenable( - this.createFunctionCompletion("adminCommand", range), - this.createFunctionCompletion("auth", range), - this.createFunctionCompletion("cloneDatabase", range), - this.createFunctionCompletion("commandHelp", range), - this.createFunctionCompletion("copyDatabase", range), - this.createFunctionCompletion("createCollection", range), - this.createFunctionCompletion("createView", range), - this.createFunctionCompletion("createUser", range), - this.createFunctionCompletion("currentOp", range), - this.createFunctionCompletion("dropDatabase", range), - this.createFunctionCompletion("eval", range), - this.createFunctionCompletion("fsyncLock", range), - this.createFunctionCompletion("fsyncUnLock", range), - this.createFunctionCompletion("getCollection", range), - this.createFunctionCompletion("getCollectionInfos", range), - this.createFunctionCompletion("getCollectionNames", range), - this.createFunctionCompletion("getLastError", range), - this.createFunctionCompletion("getLastErrorObj", range), - this.createFunctionCompletion("getLogComponents", range), - this.createFunctionCompletion("getMongo", range), - this.createFunctionCompletion("getName", range), - this.createFunctionCompletion("getPrevError", range), - this.createFunctionCompletion("getProfilingLevel", range), - this.createFunctionCompletion("getProfilingStatus", range), - this.createFunctionCompletion("getReplicationInfo", range), - this.createFunctionCompletion("getSiblingDB", range), - this.createFunctionCompletion("getWriteConcern", range), - this.createFunctionCompletion("hostInfo", range), - this.createFunctionCompletion("isMaster", range), - this.createFunctionCompletion("killOp", range), - this.createFunctionCompletion("listCommands", range), - this.createFunctionCompletion("loadServerScripts", range), - this.createFunctionCompletion("logout", range), - this.createFunctionCompletion("printCollectionStats", range), - this.createFunctionCompletion("printReplicationInfo", range), - this.createFunctionCompletion("printShardingStatus", range), - this.createFunctionCompletion("printSlaveReplicationInfo", range), - this.createFunctionCompletion("dropUser", range), - this.createFunctionCompletion("repairDatabase", range), - this.createFunctionCompletion("runCommand", range), - this.createFunctionCompletion("serverStatus", range), - this.createFunctionCompletion("setLogLevel", range), - this.createFunctionCompletion("setProfilingLevel", range), - this.createFunctionCompletion("setWriteConcern", range), - this.createFunctionCompletion("unsetWriteConcern", range), - this.createFunctionCompletion("setVerboseShell", range), - this.createFunctionCompletion("shotdownServer", range), - this.createFunctionCompletion("stats", range), - this.createFunctionCompletion("version", range) - ); - } - - private createCollectionCompletions( - range: Range - ): Promise { - if (this.db) { - return >( - this.db.collections().then((collections) => { - return collections.map( - (collection) => - { - textEdit: { - newText: collection.collectionName, - range, - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}`, - } - ); - }) - ); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions( - range: Range - ): Promise { - return this.thenable( - this.createFunctionCompletion("bulkWrite", range), - this.createFunctionCompletion("count", range), - this.createFunctionCompletion("copyTo", range), - this.createFunctionCompletion("convertToCapped", range), - this.createFunctionCompletion("createIndex", range), - this.createFunctionCompletion("createIndexes", range), - this.createFunctionCompletion("dataSize", range), - this.createFunctionCompletion("deleteOne", range), - this.createFunctionCompletion("deleteMany", range), - this.createFunctionCompletion("distinct", range), - this.createFunctionCompletion("drop", range), - this.createFunctionCompletion("dropIndex", range), - this.createFunctionCompletion("dropIndexes", range), - this.createFunctionCompletion("ensureIndex", range), - this.createFunctionCompletion("explain", range), - this.createFunctionCompletion("reIndex", range), - this.createFunctionCompletion("find", range), - this.createFunctionCompletion("findOne", range), - this.createFunctionCompletion("findOneAndDelete", range), - this.createFunctionCompletion("findOneAndReplace", range), - this.createFunctionCompletion("findOneAndUpdate", range), - this.createFunctionCompletion("getDB", range), - this.createFunctionCompletion("getPlanCache", range), - this.createFunctionCompletion("getIndexes", range), - this.createFunctionCompletion("group", range), - this.createFunctionCompletion("insert", range), - this.createFunctionCompletion("insertOne", range), - this.createFunctionCompletion("insertMany", range), - this.createFunctionCompletion("mapReduce", range), - this.createFunctionCompletion("aggregate", range), - this.createFunctionCompletion("remove", range), - this.createFunctionCompletion("replaceOne", range), - this.createFunctionCompletion("renameCollection", range), - this.createFunctionCompletion("runCommand", range), - this.createFunctionCompletion("save", range), - this.createFunctionCompletion("stats", range), - this.createFunctionCompletion("storageSize", range), - this.createFunctionCompletion("totalIndexSize", range), - this.createFunctionCompletion("update", range), - this.createFunctionCompletion("updateOne", range), - this.createFunctionCompletion("updateMany", range), - this.createFunctionCompletion("validate", range), - this.createFunctionCompletion("getShardVersion", range), - this.createFunctionCompletion("getShardDistribution", range), - this.createFunctionCompletion("getSplitKeysForChunks", range), - this.createFunctionCompletion("getWriteConcern", range), - this.createFunctionCompletion("setWriteConcern", range), - this.createFunctionCompletion("unsetWriteConcern", range), - this.createFunctionCompletion("latencyStats", range) - ); - } - - private createFunctionCompletion( - label: string, - range: Range - ): CompletionItem { - return { - textEdit: { - newText: label, - range, - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}`, - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange( - parserRuleContext.symbol.startIndex, - parserRuleContext.symbol.stopIndex - ); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange( - parserRuleContext.symbol.stopIndex + 1, - parserRuleContext.symbol.stopIndex + 1 - ); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable( - ...completionItems: CompletionItem[] - ): Promise { - return Promise.resolve(completionItems || []); - } +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { Db } from 'mongodb'; +import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; +import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { mongoLexer } from './../grammar/mongoLexer'; +import * as mongoParser from './../grammar/mongoParser'; +import { MongoVisitor } from './../grammar/visitors'; +import { SchemaService } from './schemaService'; + +export class CompletionItemsVisitor extends MongoVisitor> { + private at: Position; + + constructor( + private textDocument: TextDocument, + private db: Db, + private offset: number, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + super(); + this.at = this.textDocument.positionAt(this.offset); + } + + public visitCommands(ctx: mongoParser.CommandsContext): Promise { + return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); + } + + public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { + return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); + } + + public visitCommand(ctx: mongoParser.CommandContext): Promise { + if (ctx.childCount === 0) { + return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); + } + + const lastTerminalNode = this.getLastTerminalNode(ctx); + if (lastTerminalNode) { + return this.getCompletionItemsFromTerminalNode(lastTerminalNode); + } + return this.thenable(); + } + + public visitCollection(ctx: mongoParser.CollectionContext): Promise { + return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) + .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); + } + + public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { + const previousNode = this.getPreviousNode(ctx); + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return this.thenable(); + } + + public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { + const terminalNode = this.getLastTerminalNode(ctx); + if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { + return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); + } + return this.thenable(); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): Promise { + return ctx.parent!.accept(this); + } + + public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); + } + } + return ctx.parent!.accept(this); + } + + public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (['aggregate'].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); + } + } + return ctx.parent!.accept(this); + } + + public visitElementList(ctx: mongoParser.ElementListContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { + return ctx.parent!.accept(this); + } + + public visitLiteral(ctx: mongoParser.LiteralContext): Promise { + return ctx.parent!.accept(this); + } + + public visitTerminal(ctx: TerminalNode): Promise { + return ctx.parent!.accept(this); + } + + public visitErrorNode(ctx: ErrorNode): Promise { + return ctx.parent!.accept(this); + } + + private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { + const text = this.textDocument.getText(); + const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); + const positionOffset = this.textDocument.offsetAt(this.at); + const contextOffset = ctx.start.startIndex; + const position = document.positionAt(positionOffset - contextOffset); + return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) + .then(list => { + return list!.items.map(item => { + const startPositionOffset = document.offsetAt(item.textEdit!.range.start); + const endPositionOffset = document.offsetAt(item.textEdit!.range.end); + item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); + return item; + }); + }); + } + + private getFunctionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + return (parent)._FUNCTION_NAME.text!; + } + + private getCollectionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + let previousNode = this.getPreviousNode(parent); + if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { + previousNode = this.getPreviousNode(previousNode); + if (previousNode && previousNode instanceof mongoParser.CollectionContext) { + return previousNode.text; + } + } + return null!; + } + + private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { + if (node._symbol.type === mongoParser.mongoParser.DB) { + return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); + } + if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { + return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); + } + if (node._symbol.type === mongoParser.mongoParser.DOT) { + const previousNode = this.getPreviousNode(node); + if (previousNode && previousNode instanceof TerminalNode) { + if (previousNode._symbol.type === mongoParser.mongoParser.DB) { + return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) + .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); + } + } + if (previousNode instanceof mongoParser.CollectionContext) { + return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); + } + } + if (node instanceof ErrorNode) { + const previousNode = this.getPreviousNode(node); + if (previousNode) { + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return previousNode.accept(this); + } + } + return this.thenable(); + } + + private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { + return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; + } + + private getPreviousNode(node: ParseTree): ParseTree { + let previousNode: ParseTree = null!; + const parentNode = node.parent!; + for (let i = 0; i < parentNode.childCount; i++) { + const currentNode = parentNode.getChild(i); + if (currentNode === node) { + break; + } + previousNode = currentNode; + } + return previousNode; + } + + private createDbKeywordCompletion(range: Range): CompletionItem { + return { + textEdit: { + newText: 'db', + range + }, + kind: CompletionItemKind.Keyword, + label: 'db' + }; + } + + private createDbFunctionCompletions(range: Range): Promise { + return this.thenable( + this.createFunctionCompletion('adminCommand', range), + this.createFunctionCompletion('auth', range), + this.createFunctionCompletion('cloneDatabase', range), + this.createFunctionCompletion('commandHelp', range), + this.createFunctionCompletion('copyDatabase', range), + this.createFunctionCompletion('createCollection', range), + this.createFunctionCompletion('createView', range), + this.createFunctionCompletion('createUser', range), + this.createFunctionCompletion('currentOp', range), + this.createFunctionCompletion('dropDatabase', range), + this.createFunctionCompletion('eval', range), + this.createFunctionCompletion('fsyncLock', range), + this.createFunctionCompletion('fsyncUnLock', range), + this.createFunctionCompletion('getCollection', range), + this.createFunctionCompletion('getCollectionInfos', range), + this.createFunctionCompletion('getCollectionNames', range), + this.createFunctionCompletion('getLastError', range), + this.createFunctionCompletion('getLastErrorObj', range), + this.createFunctionCompletion('getLogComponents', range), + this.createFunctionCompletion('getMongo', range), + this.createFunctionCompletion('getName', range), + this.createFunctionCompletion('getPrevError', range), + this.createFunctionCompletion('getProfilingLevel', range), + this.createFunctionCompletion('getProfilingStatus', range), + this.createFunctionCompletion('getReplicationInfo', range), + this.createFunctionCompletion('getSiblingDB', range), + this.createFunctionCompletion('getWriteConcern', range), + this.createFunctionCompletion('hostInfo', range), + this.createFunctionCompletion('isMaster', range), + this.createFunctionCompletion('killOp', range), + this.createFunctionCompletion('listCommands', range), + this.createFunctionCompletion('loadServerScripts', range), + this.createFunctionCompletion('logout', range), + this.createFunctionCompletion('printCollectionStats', range), + this.createFunctionCompletion('printReplicationInfo', range), + this.createFunctionCompletion('printShardingStatus', range), + this.createFunctionCompletion('printSlaveReplicationInfo', range), + this.createFunctionCompletion('dropUser', range), + this.createFunctionCompletion('repairDatabase', range), + this.createFunctionCompletion('runCommand', range), + this.createFunctionCompletion('serverStatus', range), + this.createFunctionCompletion('setLogLevel', range), + this.createFunctionCompletion('setProfilingLevel', range), + this.createFunctionCompletion('setWriteConcern', range), + this.createFunctionCompletion('unsetWriteConcern', range), + this.createFunctionCompletion('setVerboseShell', range), + this.createFunctionCompletion('shotdownServer', range), + this.createFunctionCompletion('stats', range), + this.createFunctionCompletion('version', range) + ); + } + + private createCollectionCompletions(range: Range): Promise { + if (this.db) { + return >this.db.collections().then(collections => { + return collections.map(collection => ({ + textEdit: { + newText: collection.collectionName, + range + }, + label: collection.collectionName, + kind: CompletionItemKind.Property, + filterText: collection.collectionName, + sortText: `1:${collection.collectionName}` + })); + }); + } + return Promise.resolve([]); + } + + private createCollectionFunctionsCompletions(range: Range): Promise { + return this.thenable( + this.createFunctionCompletion('bulkWrite', range), + this.createFunctionCompletion('count', range), + this.createFunctionCompletion('copyTo', range), + this.createFunctionCompletion('convertToCapped', range), + this.createFunctionCompletion('createIndex', range), + this.createFunctionCompletion('createIndexes', range), + this.createFunctionCompletion('dataSize', range), + this.createFunctionCompletion('deleteOne', range), + this.createFunctionCompletion('deleteMany', range), + this.createFunctionCompletion('distinct', range), + this.createFunctionCompletion('drop', range), + this.createFunctionCompletion('dropIndex', range), + this.createFunctionCompletion('dropIndexes', range), + this.createFunctionCompletion('ensureIndex', range), + this.createFunctionCompletion('explain', range), + this.createFunctionCompletion('reIndex', range), + this.createFunctionCompletion('find', range), + this.createFunctionCompletion('findOne', range), + this.createFunctionCompletion('findOneAndDelete', range), + this.createFunctionCompletion('findOneAndReplace', range), + this.createFunctionCompletion('findOneAndUpdate', range), + this.createFunctionCompletion('getDB', range), + this.createFunctionCompletion('getPlanCache', range), + this.createFunctionCompletion('getIndexes', range), + this.createFunctionCompletion('group', range), + this.createFunctionCompletion('insert', range), + this.createFunctionCompletion('insertOne', range), + this.createFunctionCompletion('insertMany', range), + this.createFunctionCompletion('mapReduce', range), + this.createFunctionCompletion('aggregate', range), + this.createFunctionCompletion('remove', range), + this.createFunctionCompletion('replaceOne', range), + this.createFunctionCompletion('renameCollection', range), + this.createFunctionCompletion('runCommand', range), + this.createFunctionCompletion('save', range), + this.createFunctionCompletion('stats', range), + this.createFunctionCompletion('storageSize', range), + this.createFunctionCompletion('totalIndexSize', range), + this.createFunctionCompletion('update', range), + this.createFunctionCompletion('updateOne', range), + this.createFunctionCompletion('updateMany', range), + this.createFunctionCompletion('validate', range), + this.createFunctionCompletion('getShardVersion', range), + this.createFunctionCompletion('getShardDistribution', range), + this.createFunctionCompletion('getSplitKeysForChunks', range), + this.createFunctionCompletion('getWriteConcern', range), + this.createFunctionCompletion('setWriteConcern', range), + this.createFunctionCompletion('unsetWriteConcern', range), + this.createFunctionCompletion('latencyStats', range) + ); + } + + private createFunctionCompletion(label: string, range: Range): CompletionItem { + return { + textEdit: { + newText: label, + range + }, + kind: CompletionItemKind.Function, + label, + sortText: `2:${label}` + }; + } + + private createRange(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + const startToken = parserRuleContext.start; + let stopToken = parserRuleContext.stop; + if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { + stopToken = startToken; + } + + const stop = stopToken.stopIndex; + return this._createRange(startToken.startIndex, stop); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); + } + + return null!; + } + + private createRangeAfter(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + let stopToken = parserRuleContext.stop; + if (!stopToken) { + stopToken = parserRuleContext.start; + } + + const stop = stopToken.stopIndex; + return this._createRange(stop + 1, stop + 1); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); + } + + //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want + // to introduce a regression bug. + return null!; + } + + private _createRange(start: number, end: number): Range { + const endPosition = this.textDocument.positionAt(end); + if (endPosition.line < this.at.line) { + return Range.create(Position.create(this.at.line, 0), this.at); + } + const startPosition = this.textDocument.positionAt(start); + return Range.create(startPosition, endPosition); + } + + private thenable(...completionItems: CompletionItem[]): Promise { + return Promise.resolve(completionItems || []); + } + } diff --git a/Source/mongo/services/languageService.ts b/Source/mongo/services/languageService.ts index 7629c9258..83b1b594e 100644 --- a/Source/mongo/services/languageService.ts +++ b/Source/mongo/services/languageService.ts @@ -5,119 +5,86 @@ // NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) -import { Db } from "mongodb"; -import { - getLanguageService, - LanguageService as JsonLanguageService, - SchemaConfiguration, -} from "vscode-json-languageservice"; -import { - CompletionItem, - IConnection, - InitializeParams, - InitializeResult, - TextDocumentPositionParams, - TextDocuments, - TextDocumentSyncKind, -} from "vscode-languageserver"; -import { TextDocument } from "vscode-languageserver-textdocument"; -import { connectToMongoClient } from "../connectToMongoClient"; -import { IConnectionParams } from "./IConnectionParams"; -import { MongoScriptDocumentManager } from "./mongoScript"; -import { SchemaService } from "./schemaService"; +import { Db } from 'mongodb'; +import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; +import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { connectToMongoClient } from '../connectToMongoClient'; +import { IConnectionParams } from './IConnectionParams'; +import { MongoScriptDocumentManager } from './mongoScript'; +import { SchemaService } from './schemaService'; export class LanguageService { - private textDocuments: TextDocuments = new TextDocuments( - TextDocument - ); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize( - (_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ["."] }, - }, - }; - } - ); - - connection.onCompletion((textDocumentPosition) => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest( - "connect", - (connectionParams: IConnectionParams) => { - void connectToMongoClient( - connectionParams.connectionString, - connectionParams.extensionUserAgent - ).then((account) => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService - .registerSchemas(this.db) - .then((schemas) => { - this.configureSchemas(schemas); - }); - }); - } - ); - - connection.onRequest("disconnect", () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: (uri) => - this.schemaService.resolveSchema(uri), - contributions: [], - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager( - this.schemaService, - this.jsonLanguageService - ); - } - - public provideCompletionItems( - positionParams: TextDocumentPositionParams - ): Promise { - const textDocument = this.textDocuments.get( - positionParams.textDocument.uri - ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument( - textDocument!, - this.db - ); - return mongoScriptDocument.provideCompletionItemsAt( - positionParams.position - ); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas, - }); - } + + private textDocuments: TextDocuments = new TextDocuments(TextDocument); + private readonly mongoDocumentsManager: MongoScriptDocumentManager; + private db: Db; + + private jsonLanguageService: JsonLanguageService; + private schemaService: SchemaService; + private schemas: SchemaConfiguration[]; + + constructor(connection: IConnection) { + + this.schemaService = new SchemaService(); + + this.textDocuments.listen(connection); + // After the server has started the client sends an initilize request. The server receives + // in the passed params the rootPath of the workspace plus the client capabilities. + connection.onInitialize((_params: InitializeParams): InitializeResult => { + return { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode + completionProvider: { triggerCharacters: ['.'] } + } + }; + }); + + connection.onCompletion(textDocumentPosition => { + return this.provideCompletionItems(textDocumentPosition); + }); + + connection.onRequest('connect', (connectionParams: IConnectionParams) => { + void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) + .then(account => { + this.db = account.db(connectionParams.databaseName); + void this.schemaService.registerSchemas(this.db) + .then(schemas => { + this.configureSchemas(schemas); + }); + }); + }); + + connection.onRequest('disconnect', () => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.db = null!; + for (const schema of this.schemas) { + this.jsonLanguageService.resetSchema(schema.uri); + } + }); + + this.jsonLanguageService = getLanguageService({ + schemaRequestService: uri => this.schemaService.resolveSchema(uri), + contributions: [] + }); + + this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); + } + + public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { + const textDocument = this.textDocuments.get(positionParams.textDocument.uri); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); + return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); + } + + public resetSchema(uri: string): void { + this.jsonLanguageService.resetSchema(uri); + } + + public configureSchemas(schemas: SchemaConfiguration[]): void { + this.jsonLanguageService.configure({ + schemas + }); + } } diff --git a/Source/mongo/services/mongoScript.ts b/Source/mongo/services/mongoScript.ts index 4d5cb89dd..8d4c85398 100644 --- a/Source/mongo/services/mongoScript.ts +++ b/Source/mongo/services/mongoScript.ts @@ -2,133 +2,100 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; -import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; -import { Interval } from "antlr4ts/misc/Interval"; -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ParseTree } from "antlr4ts/tree/ParseTree"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Db } from "mongodb"; -import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; -import { CompletionItem, Position } from "vscode-languageserver"; -import { TextDocument } from "vscode-languageserver-textdocument"; -import { mongoLexer } from "./../grammar/mongoLexer"; -import * as mongoParser from "./../grammar/mongoParser"; -import { MongoVisitor } from "./../grammar/visitors"; -import { CompletionItemsVisitor } from "./completionItemProvider"; -import { SchemaService } from "./schemaService"; +import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; +import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; +import { Interval } from 'antlr4ts/misc/Interval'; +import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ParseTree } from 'antlr4ts/tree/ParseTree'; +import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import { Db } from 'mongodb'; +import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; +import { CompletionItem, Position } from 'vscode-languageserver'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { mongoLexer } from './../grammar/mongoLexer'; +import * as mongoParser from './../grammar/mongoParser'; +import { MongoVisitor } from './../grammar/visitors'; +import { CompletionItemsVisitor } from './completionItemProvider'; +import { SchemaService } from './schemaService'; export class MongoScriptDocumentManager { - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) {} - public getDocument( - textDocument: TextDocument, - db: Db - ): MongoScriptDocument { - return new MongoScriptDocument( - textDocument, - db, - this.schemaService, - this.jsonLanguageService - ); - } + constructor( + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + } + + public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { + return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); + } } export class MongoScriptDocument { - private readonly _lexer: mongoLexer; - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } + private readonly _lexer: mongoLexer; + + constructor( + private textDocument: TextDocument, + private db: Db, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + this._lexer = new mongoLexer(new InputStream(textDocument.getText())); + this._lexer.removeErrorListeners(); + } - public provideCompletionItemsAt( - position: Position - ): Promise { - const parser = new mongoParser.mongoParser( - new CommonTokenStream(this._lexer) - ); - parser.removeErrorListeners(); + public provideCompletionItemsAt(position: Position): Promise { + const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); + parser.removeErrorListeners(); - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor( - this.textDocument, - this.db, - offset, - this.schemaService, - this.jsonLanguageService - ).visit(lastNode); - } - return Promise.resolve([]); - } + const offset = this.textDocument.offsetAt(position); + const lastNode = new NodeFinder(offset).visit(parser.commands()); + if (lastNode) { + return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); + } + return Promise.resolve([]); + } } class NodeFinder extends MongoVisitor { - constructor(private offset: number) { - super(); - } - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } + constructor(private offset: number) { + super(); + } + + protected defaultResult(ctx: ParseTree): ParseTree { + if (ctx instanceof ParserRuleContext) { + const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; + if (stop < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + if (ctx instanceof TerminalNode) { + if (ctx.symbol.stopIndex < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } - protected aggregateResult( - aggregate: ParseTree, - nextResult: ParseTree - ): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = - aggregate instanceof ParserRuleContext - ? aggregate.start.startIndex - : (aggregate).symbol.startIndex; - const aggregateStop = - aggregate instanceof ParserRuleContext - ? aggregate.start.stopIndex - : (aggregate).symbol.stopIndex; - const nextResultStart = - nextResult instanceof ParserRuleContext - ? nextResult.start.startIndex - : (nextResult).symbol.startIndex; - const nextResultStop = - nextResult instanceof ParserRuleContext - ? nextResult.start.stopIndex - : (nextResult).symbol.stopIndex; + protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { + if (aggregate && nextResult) { + const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; + const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; + const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; + const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; - if ( - Interval.of(aggregateStart, aggregateStop).properlyContains( - Interval.of(nextResultStart, nextResultStop) - ) - ) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } + if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { + return aggregate; + } + return nextResult; + } + return nextResult ? nextResult : aggregate; + } } diff --git a/Source/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts index acb195725..cf70e8cde 100644 --- a/Source/mongo/services/schemaService.ts +++ b/Source/mongo/services/schemaService.ts @@ -5,726 +5,624 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ -import { Cursor, Db } from "mongodb"; -import { SchemaConfiguration } from "vscode-json-languageservice"; +import { Cursor, Db } from 'mongodb'; +import { SchemaConfiguration } from 'vscode-json-languageservice'; // eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from "vscode-json-languageservice/lib/umd/jsonSchema"; +import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; export class SchemaService { - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections().then((collections) => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push( - ...[ - { - uri: this.queryCollectionSchema( - collection.collectionName - ), - fileMatch: [ - this.queryDocumentUri( - collection.collectionName - ), - ], - }, - { - uri: this.aggregateCollectionSchema( - collection.collectionName - ), - fileMatch: [ - this.aggregateDocumentUri( - collection.collectionName - ), - ], - }, - ] - ); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return "mongo://query/" + collectionName + ".schema"; - } - - public aggregateCollectionSchema(collectionName: string): string { - return "mongo://aggregate/" + collectionName + ".schema"; - } - - public queryDocumentUri(collectionName: string): string { - return "mongo://query/" + collectionName + ".json"; - } - - public aggregateDocumentUri(collectionName: string): string { - return "mongo://aggregate/" + collectionName + ".json"; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith("mongo://query/")) { - return this._resolveQueryCollectionSchema( - uri.substring( - "mongo://query/".length, - uri.length - ".schema".length - ), - uri - ).then((sch) => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith("mongo://aggregate/")) { - return this._resolveAggregateCollectionSchema( - uri.substring( - "mongo://aggregate/".length, - uri.length - ".schema".length - ) - ).then((sch) => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(""); - } - - private _resolveQueryCollectionSchema( - collectionName: string, - schemaUri: string - ): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: "object", - properties: {}, - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema( - collectionName: string - ): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: "array", - items: this.getAggregateStagePropertiesSchema( - this.queryCollectionSchema(collectionName) - ), - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) - ? "array" - : document === null - ? "null" - : typeof document; - } - - private setSchemaForDocument( - parent: string, - document: any, - schema: JSONSchema - ): void { - if (this.getMongoDocumentType(document) === "object") { - for (const property of Object.keys(document)) { - if (!parent && ["_id"].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty( - parent, - property, - document, - schema - ); - } - } - } - - private setSchemaForDocumentProperty( - parent: string, - property: string, - document: any, - schema: JSONSchema - ): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, "object"], - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === "object") { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === "array") { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: "object", - description: "Performs text search", - properties: { - $search: { - type: "string", - description: - "A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase", - }, - $language: { - type: "string", - description: - 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming', - }, - $caseSensitive: { - type: "boolean", - description: - "Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index", - }, - $diacriticSensitive: { - type: "boolean", - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`, - }, - }, - required: ["$search"], - }; - - schema.properties!.$where = { - type: "string", - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`, - }; - schema.properties!.$comment = { - type: "string", - description: "Adds a comment to a query predicate", - }; - } - - private setLogicalOperatorProperties( - schema: JSONSchema, - schemaUri: string - ): void { - schema.properties!.$or = { - type: "array", - description: - "Joins query clauses with a logical OR returns all documents that match the conditions of either clause", - items: { - $ref: schemaUri, - }, - }; - schema.properties!.$and = { - type: "array", - description: - "Joins query clauses with a logical AND returns all documents that match the conditions of both clauses", - items: { - $ref: schemaUri, - }, - }; - schema.properties!.$nor = { - type: "array", - description: - "Joins query clauses with a logical NOR returns all documents that fail to match both clauses", - items: { - $ref: schemaUri, - }, - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {}, - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: "Matches values that are equal to a specified value", - }; - expressionSchema.properties.$gt = { - type: type, - description: - "Matches values that are greater than a specified value", - }; - expressionSchema.properties.$gte = { - type: type, - description: - "Matches values that are greater than or equal to a specified value", - }; - expressionSchema.properties.$lt = { - type: type, - description: "Matches values that are less than a specified value", - }; - expressionSchema.properties.$lte = { - type: type, - description: - "Matches values that are less than or equal to a specified value", - }; - expressionSchema.properties.$ne = { - type: type, - description: - "Matches all values that are not equal to a specified value", - }; - expressionSchema.properties.$in = { - type: "array", - description: "Matches any of the values specified in an array", - }; - expressionSchema.properties.$nin = { - type: "array", - description: "Matches none of the values specified in an array", - }; - - // Element operators - expressionSchema.properties.$exists = { - type: "boolean", - description: "Matches documents that have the specified field", - }; - expressionSchema.properties.$type = { - type: "string", - description: - "Selects documents if a field is of the specified type", - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: "array", - description: - "Performs a modulo operation on the value of a field and selects documents with a specified result", - maxItems: 2, - default: [2, 0], - }; - expressionSchema.properties.$regex = { - type: "string", - description: - "Selects documents where values match a specified regular expression", - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: "object", - properties: { - type: { - type: "string", - default: "GeoJSON object type", - }, - coordinates: { - type: "array", - }, - crs: { - type: "object", - properties: { - type: { - type: "string", - }, - properties: { - type: "object", - }, - }, - }, - }, - }; - expressionSchema.properties.$geoWithin = { - type: "object", - description: - "Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin", - properties: { - $geometry: geometryPropertySchema, - $box: { - type: "array", - }, - $polygon: { - type: "array", - }, - $center: { - type: "array", - }, - $centerSphere: { - type: "array", - }, - }, - }; - expressionSchema.properties.$geoIntersects = { - type: "object", - description: - "Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects", - properties: { - $geometry: geometryPropertySchema, - }, - }; - expressionSchema.properties.$near = { - type: "object", - description: - "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: "number", - }, - $minDistance: { - type: "number", - }, - }, - }; - expressionSchema.properties.$nearSphere = { - type: "object", - description: - "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: "number", - }, - $minDistance: { - type: "number", - }, - }, - }; - - // Array operatos - if (type === "array") { - expressionSchema.properties.$all = { - type: "array", - description: - "Matches arrays that contain all elements specified in the query", - }; - expressionSchema.properties.$size = { - type: "number", - description: - "Selects documents if the array field is a specified size", - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: "array", - description: - "Matches numeric or binary values in which a set of bit positions all have a value of 1", - }; - expressionSchema.properties.$bitsAnySet = { - type: "array", - description: - "Matches numeric or binary values in which any bit from a set of bit positions has a value of 1", - }; - expressionSchema.properties.$bitsAllClear = { - type: "array", - description: - "Matches numeric or binary values in which a set of bit positions all have a value of 0", - }; - expressionSchema.properties.$bitsAnyClear = { - type: "array", - description: - "Matches numeric or binary values in which any bit from a set of bit positions has a value of 0", - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: "object", - description: - "Inverts the effect of a query expression and returns documents that do not match the query expression", - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties }, - }; - schema.properties!.$elemMatch = { - type: "object", - }; - } - - private getAggregateStagePropertiesSchema( - querySchemaUri: string - ): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: "object", - properties: { - $collStats: { - type: "object", - description: - "Returns statistics regarding a collection or view", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $project: { - type: "object", - description: - "Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $match: { - type: "object", - description: - "Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)", - $ref: querySchemaUri, - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $redact: { - type: "object", - description: - "Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $limit: { - type: "object", - description: - "Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $skip: { - type: "object", - description: - "Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $unwind: { - type: "object", - description: - "Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $group: { - type: "object", - description: - "Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.", - properties: { - _id: { - type: ["string", "object"], - }, - }, - additionalProperties: { - type: "object", - }, - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $sample: { - type: "object", - description: - "Randomly selects the specified number of documents from its input", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $sort: { - type: "object", - description: - "Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $geoNear: { - type: "object", - description: - "Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $lookup: { - type: "object", - description: - "Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $out: { - type: "object", - description: - "Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $indexStats: { - type: "object", - description: - "Returns statistics regarding the use of each index for the collection", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $facet: { - type: "object", - description: - "Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $bucket: { - type: "object", - description: - "Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $bucketAuto: { - type: "object", - description: - "Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $sortByCount: { - type: "object", - description: - "Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $addFields: { - type: "object", - description: - "Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $replaceRoot: { - type: "object", - description: - "Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $count: { - type: "object", - description: - "Returns a count of the number of documents at this stage of the aggregation pipeline", - }, - }, - }); - schemas.push({ - type: "object", - properties: { - $graphLookup: { - type: "object", - description: - "Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document", - }, - }, - }); - return { - type: "object", - oneOf: schemas, - }; - } - - private readNext( - result: any[], - cursor: Cursor, - batchSize: number, - callback: (result: any[]) => void - ): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then((hasNext) => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then((doc) => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } + + private _db: Db; + private _schemasCache: Map = new Map(); + + public registerSchemas(db: Db): Thenable { + this._db = db; + this._schemasCache.clear(); + return this._db.collections() + .then(collections => { + const schemas: SchemaConfiguration[] = []; + for (const collection of collections) { + schemas.push(...[{ + uri: this.queryCollectionSchema(collection.collectionName), + fileMatch: [this.queryDocumentUri(collection.collectionName)] + }, { + uri: this.aggregateCollectionSchema(collection.collectionName), + fileMatch: [this.aggregateDocumentUri(collection.collectionName)] + }]); + } + return schemas; + }); + } + + public queryCollectionSchema(collectionName: string): string { + return 'mongo://query/' + collectionName + '.schema'; + } + + public aggregateCollectionSchema(collectionName: string): string { + return 'mongo://aggregate/' + collectionName + '.schema'; + } + + public queryDocumentUri(collectionName: string): string { + return 'mongo://query/' + collectionName + '.json'; + } + + public aggregateDocumentUri(collectionName: string): string { + return 'mongo://aggregate/' + collectionName + '.json'; + } + + public resolveSchema(uri: string): Thenable { + const schema = this._schemasCache.get(uri); + if (schema) { + return Promise.resolve(schema); + } + if (uri.startsWith('mongo://query/')) { + return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) + .then(sch => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + if (uri.startsWith('mongo://aggregate/')) { + return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) + .then(sch => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + return Promise.resolve(''); + } + + private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (result) => { + const schema: JSONSchema = { + type: 'object', + properties: {} + }; + for (const document of result) { + this.setSchemaForDocument(null!, document, schema); + } + this.setGlobalOperatorProperties(schema); + this.setLogicalOperatorProperties(schema, schemaUri); + resolve(JSON.stringify(schema)); + }); + }); + } + + private _resolveAggregateCollectionSchema(collectionName: string): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (_result) => { + const schema: JSONSchema = { + type: 'array', + items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) + }; + resolve(JSON.stringify(schema)); + }); + }); + } + + private getMongoDocumentType(document: any): string { + return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); + } + + private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { + if (this.getMongoDocumentType(document) === 'object') { + for (const property of Object.keys(document)) { + if (!parent && + ['_id'].indexOf(property) !== -1) { + continue; + } + this.setSchemaForDocumentProperty(parent, property, document, schema); + } + } + } + + private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { + const scopedProperty = parent ? `${parent}.${property}` : property; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const value = document[property]; + const type = this.getMongoDocumentType(value); + + const propertySchema: JSONSchema = { + type: [type, 'object'] + }; + this.setOperatorProperties(type, propertySchema); + schema.properties![scopedProperty] = propertySchema; + + if (type === 'object') { + this.setSchemaForDocument(scopedProperty, value, schema); + } + + if (type === 'array') { + for (const v of value) { + this.setSchemaForDocument(scopedProperty, v, schema); + } + } + } + + private setGlobalOperatorProperties(schema: JSONSchema): void { + schema.properties!.$text = { + type: 'object', + description: 'Performs text search', + properties: { + $search: { + type: 'string', + description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' + }, + $language: { + type: 'string', + description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' + }, + $caseSensitive: { + type: 'boolean', + description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' + }, + $diacriticSensitive: { + type: 'boolean', + description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index +Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` + } + }, + required: ['$search'] + }; + + schema.properties!.$where = { + type: 'string', + description: `Matches documents that satisfy a JavaScript expression. +Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` + }; + schema.properties!.$comment = { + type: 'string', + description: 'Adds a comment to a query predicate' + }; + } + + private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { + schema.properties!.$or = { + type: 'array', + description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', + items: { + $ref: schemaUri + } + }; + schema.properties!.$and = { + type: 'array', + description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', + items: { + $ref: schemaUri + } + }; + schema.properties!.$nor = { + type: 'array', + description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', + items: { + $ref: schemaUri + } + }; + } + + private setOperatorProperties(type: string, schema: JSONSchema): void { + if (!schema.properties) { + schema.properties = {}; + } + + const expressionSchema = { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: {} + }; + // Comparison operators + expressionSchema.properties.$eq = { + type: type, + description: 'Matches values that are equal to a specified value' + }; + expressionSchema.properties.$gt = { + type: type, + description: 'Matches values that are greater than a specified value' + }; + expressionSchema.properties.$gte = { + type: type, + description: 'Matches values that are greater than or equal to a specified value' + }; + expressionSchema.properties.$lt = { + type: type, + description: 'Matches values that are less than a specified value' + }; + expressionSchema.properties.$lte = { + type: type, + description: 'Matches values that are less than or equal to a specified value' + }; + expressionSchema.properties.$ne = { + type: type, + description: 'Matches all values that are not equal to a specified value' + }; + expressionSchema.properties.$in = { + type: 'array', + description: 'Matches any of the values specified in an array' + }; + expressionSchema.properties.$nin = { + type: 'array', + description: 'Matches none of the values specified in an array' + }; + + // Element operators + expressionSchema.properties.$exists = { + type: 'boolean', + description: 'Matches documents that have the specified field' + }; + expressionSchema.properties.$type = { + type: 'string', + description: 'Selects documents if a field is of the specified type' + }; + + // Evaluation operators + expressionSchema.properties.$mod = { + type: 'array', + description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', + maxItems: 2, + default: [2, 0] + }; + expressionSchema.properties.$regex = { + type: 'string', + description: 'Selects documents where values match a specified regular expression' + }; + + // Geospatial + const geometryPropertySchema: JSONSchema = { + type: 'object', + properties: { + type: { + type: 'string', + default: 'GeoJSON object type' + }, + coordinates: { + type: 'array' + }, + crs: { + type: 'object', + properties: { + type: { + type: 'string' + }, + properties: { + type: 'object' + } + } + } + } + }; + expressionSchema.properties.$geoWithin = { + type: 'object', + description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', + properties: { + $geometry: geometryPropertySchema, + $box: { + type: 'array' + }, + $polygon: { + type: 'array' + }, + $center: { + type: 'array' + }, + $centerSphere: { + type: 'array' + } + } + }; + expressionSchema.properties.$geoIntersects = { + type: 'object', + description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', + properties: { + $geometry: geometryPropertySchema + } + }; + expressionSchema.properties.$near = { + type: 'object', + description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: 'number' + }, + $minDistance: { + type: 'number' + } + } + }; + expressionSchema.properties.$nearSphere = { + type: 'object', + description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: 'number' + }, + $minDistance: { + type: 'number' + } + } + }; + + // Array operatos + if (type === 'array') { + expressionSchema.properties.$all = { + type: 'array', + description: 'Matches arrays that contain all elements specified in the query' + }; + expressionSchema.properties.$size = { + type: 'number', + description: 'Selects documents if the array field is a specified size' + }; + } + + // Bit operators + expressionSchema.properties.$bitsAllSet = { + type: 'array', + description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' + }; + expressionSchema.properties.$bitsAnySet = { + type: 'array', + description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' + }; + expressionSchema.properties.$bitsAllClear = { + type: 'array', + description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' + }; + expressionSchema.properties.$bitsAnyClear = { + type: 'array', + description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' + }; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + schema.properties = { ...expressionSchema.properties }; + schema.properties!.$not = { + type: 'object', + description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: { ...expressionSchema.properties } + }; + schema.properties!.$elemMatch = { + type: 'object' + }; + } + + private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { + const schemas: JSONSchema[] = []; + schemas.push({ + type: 'object', + properties: { + $collStats: { + type: 'object', + description: 'Returns statistics regarding a collection or view' + } + } + + }); + schemas.push({ + type: 'object', + properties: { + $project: { + type: 'object', + description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $match: { + type: 'object', + description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', + $ref: querySchemaUri + } + } + }); + schemas.push({ + type: 'object', + properties: { + $redact: { + type: 'object', + description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $limit: { + type: 'object', + description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $skip: { + type: 'object', + description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $unwind: { + type: 'object', + description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $group: { + type: 'object', + description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', + properties: { + _id: { + type: ['string', 'object'] + } + }, + additionalProperties: { + type: 'object' + } + } + } + }); + schemas.push({ + type: 'object', + properties: { + $sample: { + type: 'object', + description: 'Randomly selects the specified number of documents from its input' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $sort: { + type: 'object', + description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $geoNear: { + type: 'object', + description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $lookup: { + type: 'object', + description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $out: { + type: 'object', + description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $indexStats: { + type: 'object', + description: 'Returns statistics regarding the use of each index for the collection' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $facet: { + type: 'object', + description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $bucket: { + type: 'object', + description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $bucketAuto: { + type: 'object', + description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $sortByCount: { + type: 'object', + description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $addFields: { + type: 'object', + description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $replaceRoot: { + type: 'object', + description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $count: { + type: 'object', + description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' + } + } + }); + schemas.push({ + type: 'object', + properties: { + $graphLookup: { + type: 'object', + description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' + } + } + }); + return { + type: 'object', + oneOf: schemas + }; + } + + private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { + if (result.length === batchSize) { + callback(result); + return; + } + + void cursor.hasNext().then(hasNext => { + if (!hasNext) { + callback(result); + return; + } + + void cursor.next().then(doc => { + result.push(doc); + this.readNext(result, cursor, batchSize, callback); + }); + }); + } + } diff --git a/Source/mongo/setConnectedNode.ts b/Source/mongo/setConnectedNode.ts index bcb8e95e1..f5680d09d 100644 --- a/Source/mongo/setConnectedNode.ts +++ b/Source/mongo/setConnectedNode.ts @@ -6,10 +6,8 @@ import { ext } from "../extensionVariables"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -export function setConnectedNode( - node: MongoDatabaseTreeItem | undefined -): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); +export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { + ext.connectedMongoDB = node; + const dbName = node && node.label; + ext.mongoCodeLensProvider.setConnectedDatabase(dbName); } diff --git a/Source/mongo/tree/IMongoTreeRoot.ts b/Source/mongo/tree/IMongoTreeRoot.ts index 262e03876..d9b68980d 100644 --- a/Source/mongo/tree/IMongoTreeRoot.ts +++ b/Source/mongo/tree/IMongoTreeRoot.ts @@ -1,8 +1,9 @@ + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ export interface IMongoTreeRoot { - isEmulator: boolean | undefined; + isEmulator: boolean | undefined; } diff --git a/Source/mongo/tree/MongoAccountTreeItem.ts b/Source/mongo/tree/MongoAccountTreeItem.ts index 2f4621afb..baa870c23 100644 --- a/Source/mongo/tree/MongoAccountTreeItem.ts +++ b/Source/mongo/tree/MongoAccountTreeItem.ts @@ -3,191 +3,138 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; -import { - appendExtensionUserAgent, - AzExtParentTreeItem, - AzExtTreeItem, - ICreateChildImplContext, - parseError, -} from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import * as vscode from "vscode"; -import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { getThemeAgnosticIconPath, Links, testDb } from "../../constants"; -import { nonNullProp } from "../../utils/nonNull"; -import { connectToMongoClient } from "../connectToMongoClient"; -import { getDatabaseNameFromConnectionString } from "../mongoConnectionStrings"; -import { IMongoTreeRoot } from "./IMongoTreeRoot"; -import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; -import { MongoDatabaseTreeItem } from "./MongoDatabaseTreeItem"; -import { MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; +import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; +import { MongoClient } from 'mongodb'; +import * as vscode from 'vscode'; +import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; +import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; +import { nonNullProp } from '../../utils/nonNull'; +import { connectToMongoClient } from '../connectToMongoClient'; +import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; +import { IMongoTreeRoot } from './IMongoTreeRoot'; +import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; +import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; +import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor( - parent: AzExtParentTreeItem, - id: string, - label: string, - connectionString: string, - isEmulator: boolean | undefined, - readonly databaseAccount?: DatabaseAccountGetResults - ) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): - | string - | vscode.Uri - | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath("CosmosDBAccount.svg"); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error("Missing connection string"); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient( - this.connectionString, - this.databaseAccount - ? nonNullProp(this.databaseAccount, "name") - : appendExtensionUserAgent() - ); - - const databaseInConnectionString = - getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { - // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [ - { - name: databaseInConnectionString, - empty: false, - }, - ]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient - .db(testDb) - .admin() - .listDatabases(); - databases = result.databases; - } - return databases - .filter( - (database: IDatabaseInfo) => - !( - database.name && - database.name.toLowerCase() === "admin" && - database.empty - ) - ) // Filter out the 'admin' database if it's empty - .map( - (database) => - new MongoDatabaseTreeItem( - this, - nonNullProp(database, "name"), - this.connectionString - ) - ); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: "createMongoDatabase", - validateInput: validateDatabaseName, - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem( - this, - databaseName, - this.connectionString - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl( - context: IDeleteWizardContext - ): Promise { - await deleteCosmosDBAccount(context, this); - } + public static contextValue: string = "cosmosDBMongoServer"; + public readonly contextValue: string = MongoAccountTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly label: string; + public readonly connectionString: string; + + private _root: IMongoTreeRoot; + + constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { + super(parent); + this.id = id; + this.label = label; + this.connectionString = connectionString; + this._root = { isEmulator }; + this.valuesToMask.push(connectionString); + } + + // overrides ISubscriptionContext with an object that also has Mongo info + public get root(): IMongoTreeRoot { + return this._root; + } + + public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath('CosmosDBAccount.svg'); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + let mongoClient: MongoClient | undefined; + try { + let databases: IDatabaseInfo[]; + + if (!this.connectionString) { + throw new Error('Missing connection string'); + } + + // Azure MongoDB accounts need to have the name passed in for private endpoints + mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); + + const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); + if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format + // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) + databases = [{ + name: databaseInConnectionString, + empty: false + }]; + } else { + // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); + databases = result.databases; + } + return databases + .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty + .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); + } catch (error) { + const message = parseError(error).message; + if (this._root.isEmulator && message.includes("ECONNREFUSED")) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; + } + throw error; + } + finally { + if (mongoClient) { + void mongoClient.close(); + } + } + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: 'createMongoDatabase', + validateInput: validateDatabaseName + }); + context.showCreatingTreeItem(databaseName); + + return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case MongoDatabaseTreeItem.contextValue: + case MongoCollectionTreeItem.contextValue: + case MongoDocumentTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { + await deleteCosmosDBAccount(context, this); + } } -export function validateDatabaseName( - database: string -): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return 'Database name cannot contain these characters - `/\\. "$#?=`'; - } - return undefined; +export function validateDatabaseName(database: string): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions + // "#?" are restricted characters for CosmosDB - MongoDB accounts + const min = 1; + const max = 63; + if (!database || database.length < min || database.length > max) { + return `Database name must be between ${min} and ${max} characters.`; + } + if (/[/\\. "$#?=]/.test(database)) { + return "Database name cannot contain these characters - `/\\. \"$#?=`"; + } + return undefined; } export interface IDatabaseInfo { - name?: string; - empty?: boolean; + name?: string; + empty?: boolean; } diff --git a/Source/mongo/tree/MongoCollectionTreeItem.ts b/Source/mongo/tree/MongoCollectionTreeItem.ts index b4dd4f68f..eca0c8d32 100644 --- a/Source/mongo/tree/MongoCollectionTreeItem.ts +++ b/Source/mongo/tree/MongoCollectionTreeItem.ts @@ -5,473 +5,316 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { - AzExtParentTreeItem, - AzExtTreeItem, - DialogResponses, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as assert from "assert"; -import { - BulkWriteOpResultObject, - Collection, - CollectionInsertManyOptions, - Cursor, - DeleteWriteOpResultObject, - InsertOneWriteOpResult, - InsertWriteOpResult, - MongoCountPreferences, -} from "mongodb"; -import * as _ from "underscore"; -import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { nonNullValue } from "../../utils/nonNull"; -import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; -import { getBatchSizeSetting } from "../../utils/workspacUtils"; -import { MongoCommand } from "../MongoCommand"; -import { IMongoDocument, MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; +import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as assert from 'assert'; +import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; +import * as _ from 'underscore'; +import * as vscode from 'vscode'; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { nonNullValue } from '../../utils/nonNull'; +import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; +import { getBatchSizeSetting } from '../../utils/workspacUtils'; +import { MongoCommand } from '../MongoCommand'; +import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; type MongoDocument = { _id: string }; class FunctionDescriptor { - public constructor( - public mongoFunction: MongoFunction, - public text: string, - public minShellArgs: number, - public maxShellArgs: number, - public maxHandledArgs: number - ) {} + public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { + } } -export class MongoCollectionTreeItem - extends AzExtParentTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor( - parent: AzExtParentTreeItem, - collection: Collection, - findArgs?: {}[] - ) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent( - context: IActionContext, - content: string - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, "_id"), - upsert: false, - }, - }; - }); - - const result: BulkWriteOpResultObject = - await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog( - `Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)` - ); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all( - nodesToRefresh.map((n) => n.refreshChildren(context, documents)) - ); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = ( - await this.getCachedChildren(context) - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify( - children.map((c) => c.document), - null, - 2 - ); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("files"); - } - - public get filePath(): string { - return this.label + "-cosmos-collection.json"; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren( - context: IActionContext, - docs: IMongoDocument[] - ): Promise { - const documentNodes = ( - await this.getCachedChildren(context) - ); - for (const doc of docs) { - const documentNode = documentNodes.find( - (node) => node.document._id.toString() === doc._id.toString() - ); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection - .find(this._query) - .batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - "invalidMongoDocument", - (doc) => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = - await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue( - await this.collection.findOne({ _id: result.insertedId }), - "newDocument" - ); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly( - command: Partial - ): Promise< - | { deferToShell: true; result: undefined } - | { deferToShell: false; result: string } - > { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments - ? command.arguments.map(parseJSContent) - : []; - - const functions = { - drop: new FunctionDescriptor( - this.drop, - "Dropping collection", - 0, - 0, - 0 - ), - count: new FunctionDescriptor( - this.count, - "Counting documents", - 0, - 2, - 2 - ), - findOne: new FunctionDescriptor( - this.findOne, - "Finding document", - 0, - 2, - 2 - ), - insert: new FunctionDescriptor( - this.insert, - "Inserting document", - 1, - 1, - 1 - ), - insertMany: new FunctionDescriptor( - this.insertMany, - "Inserting documents", - 1, - 2, - 2 - ), - insertOne: new FunctionDescriptor( - this.insertOne, - "Inserting document", - 1, - 2, - 2 - ), - deleteMany: new FunctionDescriptor( - this.deleteMany, - "Deleting documents", - 1, - 2, - 1 - ), - deleteOne: new FunctionDescriptor( - this.deleteOne, - "Deleting document", - 1, - 2, - 1 - ), - remove: new FunctionDescriptor( - this.remove, - "Deleting document(s)", - 1, - 2, - 1 - ), - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error( - `Too few arguments passed to command ${command.name}.` - ); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error( - `Too many arguments passed to command ${command.name}` - ); - } - if (parameters.length > descriptor.maxHandledArgs) { - //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress( - descriptor.mongoFunction.apply(this, parameters), - descriptor.text - ); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteMongoCollection" }, - DialogResponses.deleteResponse - ); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number; name?: string } = e; - const NamespaceNotFoundCode = 26; - if ( - error.name === "MongoError" && - error.code === NamespaceNotFoundCode - ) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne( - query?: Object, - fieldsOption?: Object - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { - fields: fieldsOption, - }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, "\t"); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error( - "The insert command requires at least one argument" - ); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = - await this.collection.insertOne(document, { - w: options && options.writeConcern, - }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual( - documents.length, - 0, - "Array of documents cannot be empty" - ); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = - await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = - await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = - await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count( - query?: Object[], - options?: MongoCountPreferences - ): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, "\t"); - } +export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { + public static contextValue: string = "MongoCollection"; + public readonly contextValue: string = MongoCollectionTreeItem.contextValue; + public readonly childTypeLabel: string = "Document"; + public readonly collection: Collection; + public parent: AzExtParentTreeItem; + public findArgs?: {}[]; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + + private readonly _query: object | undefined; + private readonly _projection: object | undefined; + private _cursor: Cursor | undefined; + private _hasMoreChildren: boolean = true; + private _batchSize: number = getBatchSizeSetting(); + + constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { + super(parent); + this.collection = collection; + this.findArgs = findArgs; + if (findArgs && findArgs.length) { + this._query = findArgs[0]; + this._projection = findArgs.length > 1 ? findArgs[1] : undefined; + } + ext.fileSystem.fireChangedEvent(this); + } + + public async writeFileContent(context: IActionContext, content: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const documents: IMongoDocument[] = EJSON.parse(content); + const operations = documents.map((document) => { + return { + replaceOne: { + filter: { _id: document._id }, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + replacement: _.omit(document, '_id'), + upsert: false + } + }; + }); + + const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); + ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); + + // The current tree item may have been a temporary one used to execute a scrapbook command. + // We want to refresh children for this one _and_ the actual one in the tree (if it's different) + const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); + const nodesToRefresh: MongoCollectionTreeItem[] = [this]; + if (nodeInTree && this !== nodeInTree) { + nodesToRefresh.push(nodeInTree); + } + + await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); + + if (nodeInTree && this !== nodeInTree) { + // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different + ext.fileSystem.fireChangedEvent(nodeInTree); + } + } + + public async getFileContent(context: IActionContext): Promise { + const children = await this.getCachedChildren(context); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(children.map(c => c.document), null, 2); + } + + public get id(): string { + return this.collection.collectionName; + } + + public get label(): string { + return this.collection.collectionName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('files'); + } + + public get filePath(): string { + return this.label + '-cosmos-collection.json'; + } + + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + ext.fileSystem.fireChangedEvent(this); + } + + public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { + const documentNodes = await this.getCachedChildren(context); + for (const doc of docs) { + const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); + if (documentNode) { + documentNode.document = doc; + await documentNode.refresh(context); + } + } + } + + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } + + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (clearCache || this._cursor === undefined) { + this._cursor = this.collection.find(this._query).batchSize(this._batchSize); + if (this._projection) { + this._cursor = this._cursor.project(this._projection); + } + } + + const documents: IMongoDocument[] = []; + let count: number = 0; + while (count < this._batchSize) { + this._hasMoreChildren = await this._cursor.hasNext(); + if (this._hasMoreChildren) { + documents.push(await this._cursor.next()); + count += 1; + } else { + break; + } + } + this._batchSize *= 2; + + return this.createTreeItemsWithErrorHandling( + documents, + 'invalidMongoDocument', + doc => new MongoDocumentTreeItem(this, doc), + getDocumentTreeItemLabel + ); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + context.showCreatingTreeItem(""); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: InsertOneWriteOpResult = await this.collection.insertOne({}); + const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); + return new MongoDocumentTreeItem(this, newDocument); + } + + public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { + // range and text are not neccessary properties for this function so partial should suffice + const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; + + const functions = { + drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), + count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), + findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), + insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), + insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), + insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), + deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), + deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), + remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) + }; + + // eslint-disable-next-line no-prototype-builtins + if (command.name && functions.hasOwnProperty(command.name)) { + // currently no logic to handle chained commands so just defer to the shell right away + if (command.chained) { + return { deferToShell: true, result: undefined }; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const descriptor: FunctionDescriptor = functions[command.name]; + + if (parameters.length < descriptor.minShellArgs) { + throw new Error(`Too few arguments passed to command ${command.name}.`); + } + if (parameters.length > descriptor.maxShellArgs) { + throw new Error(`Too many arguments passed to command ${command.name}`); + } + if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will + return { deferToShell: true, result: undefined }; + } + const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); + return { deferToShell: false, result }; + } + return { deferToShell: true, result: undefined }; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); + await this.drop(); + } + + private async drop(): Promise { + try { + await this.collection.drop(); + return `Dropped collection '${this.collection.collectionName}'.`; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const error: { code?: number, name?: string } = e; + const NamespaceNotFoundCode = 26; + if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { + return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; + } else { + throw error; + } + } + } + + private async findOne(query?: Object, fieldsOption?: Object): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); + // findOne is the only command in this file whose output requires EJSON support. + // Hence that's the only function which uses EJSON.stringify rather than this.stringify. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(result, null, '\t'); + } + + private async insert(document: Object): Promise { + if (!document) { + throw new Error("The insert command requires at least one argument"); + } + + const insertResult = await this.collection.insert(document); + return this.stringify(insertResult); + } + + private async insertOne(document: Object, options?: any): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); + return this.stringify(insertOneResult); + } + + private async insertMany(documents: any[], options?: any): Promise { + assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); + const insertManyOptions: CollectionInsertManyOptions = {}; + if (options) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.ordered) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.ordered = options.ordered; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.writeConcern) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.w = options.writeConcern; + } + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); + return this.stringify(insertManyResult); + } + + private async remove(filter: Object): Promise { + const removeResult = await this.collection.remove(filter); + return this.stringify(removeResult); + } + + private async deleteOne(filter: Object): Promise { + const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); + return this.stringify(deleteOneResult); + } + + private async deleteMany(filter: Object): Promise { + const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); + return this.stringify(deleteOpResult); + } + + private async count(query?: Object[], options?: MongoCountPreferences): Promise { + const count = await this.collection.count(query, options); + return this.stringify(count); + } + + private stringify(result: any): string { + return JSON.stringify(result, null, '\t'); + } } function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title, - }, - (_progress) => { - return promise; - } - ); + return vscode.window.withProgress( + { + location: vscode.ProgressLocation.Window, + title: title + }, + (_progress) => { + return promise; + }); } function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.parse(content); + } catch (error) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + throw error.message; + } } diff --git a/Source/mongo/tree/MongoDatabaseTreeItem.ts b/Source/mongo/tree/MongoDatabaseTreeItem.ts index 1fed13c80..73a7c6a22 100644 --- a/Source/mongo/tree/MongoDatabaseTreeItem.ts +++ b/Source/mongo/tree/MongoDatabaseTreeItem.ts @@ -3,383 +3,256 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - appendExtensionUserAgent, - AzExtParentTreeItem, - DialogResponses, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, - UserCancelledError, -} from "@microsoft/vscode-azext-utils"; -import * as fse from "fs-extra"; -import { Collection, Db, DbCollectionOptions } from "mongodb"; -import * as path from "path"; -import * as process from "process"; -import * as vscode from "vscode"; -import { ext } from "../../extensionVariables"; -import * as cpUtils from "../../utils/cp"; -import { nonNullProp, nonNullValue } from "../../utils/nonNull"; -import { connectToMongoClient } from "../connectToMongoClient"; -import { MongoCommand } from "../MongoCommand"; -import { addDatabaseToAccountConnectionString } from "../mongoConnectionStrings"; -import { MongoShell } from "../MongoShell"; -import { IMongoTreeRoot } from "./IMongoTreeRoot"; -import { MongoAccountTreeItem } from "./MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; - -const mongoExecutableFileName = - process.platform === "win32" ? "mongo.exe" : "mongo"; +import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import { Collection, Db, DbCollectionOptions } from 'mongodb'; +import * as path from 'path'; +import * as process from 'process'; +import * as vscode from 'vscode'; +import { ext } from '../../extensionVariables'; +import * as cpUtils from '../../utils/cp'; +import { nonNullProp, nonNullValue } from '../../utils/nonNull'; +import { connectToMongoClient } from '../connectToMongoClient'; +import { MongoCommand } from '../MongoCommand'; +import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; +import { MongoShell } from '../MongoShell'; +import { IMongoTreeRoot } from './IMongoTreeRoot'; +import { MongoAccountTreeItem } from './MongoAccountTreeItem'; +import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; + +const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; const executingInShellMsg = "Executing command in Mongo shell"; export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor( - parent: MongoAccountTreeItem, - databaseName: string, - connectionString: string - ) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString( - connectionString, - this.databaseName - ); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && - ext.connectedMongoDB.fullId === this.fullId - ? "Connected" - : ""; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("database"); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map( - (collection) => new MongoCollectionTreeItem(this, collection) - ); - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: "createMongoCollection", - validateInput: validateMongoCollectionName, - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteMongoDatabase" }, - DialogResponses.deleteResponse - ); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient( - this.connectionString, - appendExtensionUserAgent() - ); - return accountConnection.db(this.databaseName); - } - - public async executeCommand( - command: MongoCommand, - context: IActionContext - ): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem( - this, - collection, - command.arguments - ); - const result = - await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress( - this.executeCommandInShell(command, context), - executingInShellMsg - ); - } - - if (command.name === "createCollection") { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress( - this.createCollection( - stripQuotes(nonNullProp(command, "arguments")[0]), - nonNullProp(command, "argumentObjects")[1] - ).then(() => JSON.stringify({ Created: "Ok" })), - "Creating collection" - ); - } else { - return withProgress( - this.executeCommandInShell(command, context), - executingInShellMsg - ); - } - } - - public async createCollection( - collectionName: string, - options?: DbCollectionOptions - ): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection( - collectionName, - options - ); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell( - command: MongoCommand, - context: IActionContext - ): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get( - ext.settingsKeys.mongoShellPath - ); - const shellArgs: string[] = config.get( - ext.settingsKeys.mongoShellArgs, - [] - ); - - if ( - !shellPath || - !this._cachedShellPathOrCmd || - this._previousShellPathSetting !== shellPath - ) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = - 1000 * - nonNullValue( - config.get(ext.settingsKeys.mongoShellTimeout), - "mongoShellTimeout" - ); - return MongoShell.create( - shellPath, - shellArgs, - this.connectionString, - this.root.isEmulator, - ext.outputChannel, - timeout - ); - } - - private async _determineShellPathOrCmd( - context: IActionContext, - shellPathSetting: string | undefined - ): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds("mongo", "--version")) { - // If the user already has mongo in their system path, just use that - return "mongo"; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { - title: `Browse to ${mongoExecutableFileName}`, - }; - const browse: vscode.MessageItem = { - title: "Open installation page", - }; - const noMongoError: string = - "This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting."; - const response = await context.ui.showWarningMessage( - noMongoError, - { stepName: "promptForMongoPath" }, - browse, - openFile - ); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = - await context.ui.showOpenDialog({ - filters: { - "Executable Files": [ - process.platform === "win32" - ? "exe" - : "", - ], - }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: "openMongoExeFile", - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { - title: "Use anyway", - }; - const tryAgain: vscode.MessageItem = { - title: "Try again", - }; - const response2 = - await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: "confirmMongoExeFile" }, - useAnyway, - tryAgain - ); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace - .getConfiguration() - .update( - ext.settingsKeys.mongoShellPath, - fsPath, - vscode.ConfigurationTarget.Global - ); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand( - "vscode.open", - vscode.Uri.parse( - "https://docs.mongodb.com/manual/installation/" - ) - ); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError("createShell"); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } + public static contextValue: string = "mongoDb"; + public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; + public readonly connectionString: string; + public readonly databaseName: string; + public readonly parent: MongoAccountTreeItem; + + private _previousShellPathSetting: string | undefined; + private _cachedShellPathOrCmd: string | undefined; + + constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { + super(parent); + this.databaseName = databaseName; + this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); + } + + public get root(): IMongoTreeRoot { + return this.parent.root; + } + + public get label(): string { + return this.databaseName; + } + + public get description(): string { + return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; + } + + public get id(): string { + return this.databaseName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('database'); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + const db: Db = await this.connectToDb(); + const collections: Collection[] = await db.collections(); + return collections.map(collection => new MongoCollectionTreeItem(this, collection)); + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + const collectionName = await context.ui.showInputBox({ + placeHolder: "Collection Name", + prompt: "Enter the name of the collection", + stepName: 'createMongoCollection', + validateInput: validateMongoCollectionName + }); + + context.showCreatingTreeItem(collectionName); + return await this.createCollection(collectionName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); + const db = await this.connectToDb(); + await db.dropDatabase(); + } + + public async connectToDb(): Promise { + const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); + return accountConnection.db(this.databaseName); + } + + public async executeCommand(command: MongoCommand, context: IActionContext): Promise { + if (command.collection) { + const db = await this.connectToDb(); + const collection = db.collection(command.collection); + if (collection) { + const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); + const result = await collectionTreeItem.tryExecuteCommandDirectly(command); + if (!result.deferToShell) { + return result.result; + } + } + return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); + + } + + if (command.name === 'createCollection') { + // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead + return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); + } else { + return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); + } + } + + public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { + const db: Db = await this.connectToDb(); + const newCollection: Collection = await db.createCollection(collectionName, options); + // db.createCollection() doesn't create empty collections for some reason + // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection + const result = await newCollection.insertOne({}); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + await newCollection.deleteOne({ _id: result.insertedId }); + return new MongoCollectionTreeItem(this, newCollection); + } + + private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { + context.telemetry.properties.executeInShell = "true"; + + if (this.root.isEmulator) { + // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info + await this.connectToDb(); + } + + // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state + // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out + // requests. + const shell = await this.createShell(context); + try { + await shell.useDatabase(this.databaseName); + return await shell.executeScript(command.text); + } finally { + shell.dispose(); + } + } + + private async createShell(context: IActionContext): Promise { + const config = vscode.workspace.getConfiguration(); + let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); + const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); + + if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { + // Only do this if setting changed since last time + shellPath = await this._determineShellPathOrCmd(context, shellPath); + this._previousShellPathSetting = shellPath; + } + this._cachedShellPathOrCmd = shellPath; + + const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); + return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); + } + + private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { + if (!shellPathSetting) { + // User hasn't specified the path + if (await cpUtils.commandSucceeds('mongo', '--version')) { + // If the user already has mongo in their system path, just use that + return 'mongo'; + } else { + // If all else fails, prompt the user for the mongo path + const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; + const browse: vscode.MessageItem = { title: 'Open installation page' }; + const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; + const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); + if (response === openFile) { + // eslint-disable-next-line no-constant-condition + while (true) { + const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ + filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, + openLabel: `Select ${mongoExecutableFileName}`, + stepName: 'openMongoExeFile', + }); + const fsPath = newPath[0].fsPath; + const baseName = path.basename(fsPath); + if (baseName !== mongoExecutableFileName) { + const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; + const tryAgain: vscode.MessageItem = { title: 'Try again' }; + const response2 = await context.ui.showWarningMessage( + `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, + { stepName: 'confirmMongoExeFile' }, + useAnyway, + tryAgain); + if (response2 === tryAgain) { + continue; + } + } + + await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); + return fsPath; + } + } else if (response === browse) { + void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); + // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath + } + + throw new UserCancelledError('createShell'); + } + } else { + // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix + if (await fse.pathExists(shellPathSetting)) { + const stat = await fse.stat(shellPathSetting); + if (stat.isDirectory()) { + return path.join(shellPathSetting, mongoExecutableFileName); + } + } + + return shellPathSetting; + } + } } -export function validateMongoCollectionName( - collectionName: string -): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; +export function validateMongoCollectionName(collectionName: string): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names + if (!collectionName) { + return "Collection name cannot be empty"; + } + const systemPrefix = "system."; + if (collectionName.startsWith(systemPrefix)) { + return `"${systemPrefix}" prefix is reserved for internal use`; + } + if (/[$]/.test(collectionName)) { + return "Collection name cannot contain $"; + } + return undefined; } -function withProgress( - promise: Thenable, - title: string, - location: vscode.ProgressLocation = vscode.ProgressLocation.Window -): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title, - }, - (_progress) => { - return promise; - } - ); +function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { + return vscode.window.withProgress( + { + location: location, + title: title + }, + (_progress) => { + return promise; + }); } export function stripQuotes(term: string): string { - if ( - (term.startsWith("'") && term.endsWith("'")) || - (term.startsWith('"') && term.endsWith('"')) - ) { - return term.substring(1, term.length - 1); - } - return term; + if ((term.startsWith('\'') && term.endsWith('\'')) + || (term.startsWith('"') && term.endsWith('"'))) { + return term.substring(1, term.length - 1); + } + return term; } diff --git a/Source/mongo/tree/MongoDocumentTreeItem.ts b/Source/mongo/tree/MongoDocumentTreeItem.ts index dae87ed84..ad44e43c3 100644 --- a/Source/mongo/tree/MongoDocumentTreeItem.ts +++ b/Source/mongo/tree/MongoDocumentTreeItem.ts @@ -3,131 +3,95 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - DialogResponses, - IActionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { - Collection, - DeleteWriteOpResultObject, - ObjectID, - UpdateWriteOpResult, -} from "mongodb"; -import * as _ from "underscore"; -import * as vscode from "vscode"; -import { IEditableTreeItem } from "../../DatabasesFileSystem"; -import { ext } from "../../extensionVariables"; -import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; -import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; +import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; +import * as _ from 'underscore'; +import * as vscode from 'vscode'; +import { IEditableTreeItem } from '../../DatabasesFileSystem'; +import { ext } from '../../extensionVariables'; +import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; +import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); export interface IMongoDocument { - _id: string | ObjectID; + _id: string | ObjectID; - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + // custom properties + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [key: string]: any; } -export class MongoDocumentTreeItem - extends AzExtTreeItem - implements IEditableTreeItem -{ - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); +export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { + public static contextValue: string = "MongoDocument"; + public readonly contextValue: string = MongoDocumentTreeItem.contextValue; + public document: IMongoDocument; + public readonly parent: MongoCollectionTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); - private _label: string; + private _label: string; - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = "cosmosDB.openDocument"; - ext.fileSystem.fireChangedEvent(this); - } + constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { + super(parent); + this.document = document; + this._label = getDocumentTreeItemLabel(this.document); + this.commandId = 'cosmosDB.openDocument'; + ext.fileSystem.fireChangedEvent(this); + } - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } + public get id(): string { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return String(this.document!._id); + } - public get label(): string { - return this._label; - } + public get label(): string { + return this._label; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("file"); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('file'); + } - public get filePath(): string { - return this.label + "-cosmos-document.json"; - } + public get filePath(): string { + return this.label + '-cosmos-document.json'; + } - public static async update( - collection: Collection, - newDocument: IMongoDocument - ): Promise { - if (!newDocument._id) { - throw new Error( - `The "_id" field is required to update a document.` - ); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne( - filter, - _.omit(newDocument, "_id") - ); - if (result.modifiedCount !== 1) { - throw new Error( - `Failed to update document with _id '${newDocument._id}'.` - ); - } - return newDocument; - } + public static async update(collection: Collection, newDocument: IMongoDocument): Promise { + if (!newDocument._id) { + throw new Error(`The "_id" field is required to update a document.`); + } + const filter: object = { _id: newDocument._id }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); + if (result.modifiedCount !== 1) { + throw new Error(`Failed to update document with _id '${newDocument._id}'.`); + } + return newDocument; + } - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } + public async getFileContent(): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(this.document, null, 2); + } - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this.document); + ext.fileSystem.fireChangedEvent(this); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deleteMongoDocument" }, - DialogResponses.deleteResponse - ); - const deleteResult: DeleteWriteOpResultObject = - await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error( - `Failed to delete document with _id '${this.document._id}'.` - ); - } - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this._label}'?`; + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); + const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); + if (deleteResult.deletedCount !== 1) { + throw new Error(`Failed to delete document with _id '${this.document._id}'.`); + } + } - public async writeFileContent( - _context: IActionContext, - content: string - ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update( - this.parent.collection, - newDocument - ); - } + public async writeFileContent(_context: IActionContext, content: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const newDocument: IMongoDocument = EJSON.parse(content); + this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); + } } diff --git a/Source/postgres/abstract/AbstractPostgresClient.ts b/Source/postgres/abstract/AbstractPostgresClient.ts index ca6bd3d9a..c1fa29c4f 100644 --- a/Source/postgres/abstract/AbstractPostgresClient.ts +++ b/Source/postgres/abstract/AbstractPostgresClient.ts @@ -6,26 +6,18 @@ import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../../utils/azureClients"; +import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; import { PostgresServerType } from "./models"; -export type AbstractPostgresClient = - | PostgreSQLFlexibleManagementClient - | PostgreSQLSingleManagementClient; +export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; -export async function createAbstractPostgresClient( - serverType: PostgresServerType, - context: AzExtClientContext -): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context); - case PostgresServerType.Single: - return await createPostgreSQLClient(context); - default: - throw new Error("Service not implemented."); - } +export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { + switch (serverType) { + case PostgresServerType.Flexible: + return await createPostgreSQLFlexibleClient(context) + case PostgresServerType.Single: + return await createPostgreSQLClient(context) + default: + throw new Error("Service not implemented."); + } } diff --git a/Source/postgres/abstract/models.ts b/Source/postgres/abstract/models.ts index 046185de1..6bdadf16a 100644 --- a/Source/postgres/abstract/models.ts +++ b/Source/postgres/abstract/models.ts @@ -7,58 +7,49 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; export enum PostgresServerType { - Flexible = "Flexible", - Single = "Single", + Flexible = 'Flexible', + Single = 'Single' } -export type PostgresAbstractServer = ( - | SingleModels.Server - | FlexibleModels.Server -) & { serverType?: PostgresServerType }; +export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } -export type PostgresAbstractDatabase = - | SingleModels.Database - | FlexibleModels.Database; +export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; /** * Billing information related properties of a server. */ export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; + /** + * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + */ + name: string; + /** + * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', + * 'GeneralPurpose', 'MemoryOptimized' + */ + tier: SingleModels.SkuTier | FlexibleModels.SkuTier; + /** + * The scale up/out capacity, representing server's compute units. + */ + capacity?: number; + /** + * The size code, to be interpreted by resource as appropriate. + */ + size?: string; + /** + * The family of hardware. + */ + family?: string; } export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; + location: string; + sku: AbstractSku; + administratorLogin: string; + administratorLoginPassword: string; + size: number; } -export type AbstractNameAvailability = - | SingleModels.NameAvailability - | FlexibleModels.NameAvailability; +export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; -export type AbstractFirewallRule = - | SingleModels.FirewallRule - | FlexibleModels.FirewallRule; +export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; diff --git a/Source/postgres/commands/checkAuthentication.ts b/Source/postgres/commands/checkAuthentication.ts index c26bc25be..6799d060c 100644 --- a/Source/postgres/commands/checkAuthentication.ts +++ b/Source/postgres/commands/checkAuthentication.ts @@ -3,11 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - IActionContext, - IParsedError, - parseError, -} from "@microsoft/vscode-azext-utils"; +import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; import { invalidCredentialsErrorType } from "../postgresConstants"; import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; @@ -15,34 +11,26 @@ import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; import { configurePostgresFirewall } from "./configurePostgresFirewall"; import { enterPostgresCredentials } from "./enterPostgresCredentials"; -export async function checkAuthentication( - context: IActionContext, - treeItem: PostgresDatabaseTreeItem -): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = - await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = - await PostgresClientConfigFactory.getClientConfigFromNode( - treeItem.parent, - treeItem.databaseName - ); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); +export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { + let clientConfig: ClientConfig | undefined; + while (!clientConfig) { + const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + await configurePostgresFirewall(context, treeItem.parent); + continue; + } + try { + const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); + clientConfig = getClientConfigResult.clientConfig; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; + if (parsedError.errorType === invalidCredentialsErrorType) { + await enterPostgresCredentials(context, treeItem.parent); + } else { + throw error; + } + } + } + return clientConfig; } diff --git a/Source/postgres/commands/configurePostgresFirewall.ts b/Source/postgres/commands/configurePostgresFirewall.ts index 86779ff9b..52a378fca 100644 --- a/Source/postgres/commands/configurePostgresFirewall.ts +++ b/Source/postgres/commands/configurePostgresFirewall.ts @@ -4,102 +4,66 @@ *--------------------------------------------------------------------------------------------*/ import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; +import * as vscode from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { getPublicIpv4 } from "../../utils/getIp"; import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { randomUtils } from "../../utils/randomUtils"; -import { - AbstractPostgresClient, - createAbstractPostgresClient, -} from "../abstract/AbstractPostgresClient"; -import { AbstractFirewallRule, PostgresServerType } from "../abstract/models"; +import { nonNullProp } from '../../utils/nonNull'; +import { randomUtils } from '../../utils/randomUtils'; +import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; +import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function configurePostgresFirewall( - context: IActionContext, - treeItem?: PostgresServerTreeItem -): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } +export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize( - "firewallRuleWillBeAdded", - 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', - ip, - treeItem.label - ), - { - modal: true, - stepName: "postgresAddFirewallRule", - }, - { title: DialogResponses.yes.title } - ); + const ip: string = await getPublicIp(context); + await context.ui.showWarningMessage( + localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), + { + modal: true, + stepName: 'postgresAddFirewallRule' + }, + { title: DialogResponses.yes.title } + ); - await setFirewallRule(context, treeItem, ip); + await setFirewallRule(context, treeItem, ip); } -export async function setFirewallRule( - context: IActionContext, - treeItem: PostgresServerTreeItem, - ip: string -): Promise { - const serverType: PostgresServerType = nonNullProp(treeItem, "serverType"); - const client: AbstractPostgresClient = await createAbstractPostgresClient( - serverType, - [context, treeItem.subscription] - ); - const resourceGroup: string = nonNullProp(treeItem, "resourceGroup"); - const serverName: string = nonNullProp(treeItem, "azureName"); +export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { - const firewallRuleName: string = - "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; + const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); + const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); + const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); + const serverName: string = nonNullProp(treeItem, 'azureName'); - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip, - }; + const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - const progressMessage: string = localize( - "configuringFirewallRule", - 'Adding firewall rule for IP "{0}" to server "{1}"...', - ip, - serverName - ); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage, - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait( - resourceGroup, - serverName, - firewallRuleName, - newFirewallRule - ); - }); - const completedMessage: string = localize( - "addedFirewallRule", - 'Successfully added firewall rule for IP "{0}" to server "{1}".', - ip, - serverName - ); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); + const newFirewallRule: AbstractFirewallRule = { + startIpAddress: ip, + endIpAddress: ip + }; + + const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage + }; + ext.outputChannel.appendLog(progressMessage); + await vscode.window.withProgress(options, async () => { + await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); + }); + const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + await treeItem.refresh(context); } export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); + return await getPublicIpv4(context); } diff --git a/Source/postgres/commands/connectPostgresDatabase.ts b/Source/postgres/commands/connectPostgresDatabase.ts index 9437c8c70..6996f7d03 100644 --- a/Source/postgres/commands/connectPostgresDatabase.ts +++ b/Source/postgres/commands/connectPostgresDatabase.ts @@ -4,52 +4,36 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from "vscode"; -import { - connectedPostgresKey, - postgresFlexibleFilter, - postgresSingleFilter, -} from "../../constants"; +import { Uri, window } from 'vscode'; +import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; import { ext } from "../../extensionVariables"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function connectPostgresDatabase( - context: IActionContext, - treeItem?: Uri | PostgresDatabaseTreeItem -): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } +export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { + if (!treeItem || treeItem instanceof Uri) { + if (treeItem) { + void window.showTextDocument(treeItem); + } + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } - const oldTreeItemId: string | undefined = - ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); + const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; + void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); + ext.connectedPostgresDB = treeItem; + const database = treeItem && treeItem.label; + if (ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(database); + } + await treeItem.refresh(context); - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - oldTreeItemId, - context - ); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } + if (oldTreeItemId) { + // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); + if (oldTreeItem) { + await oldTreeItem.refresh(context); + } + } } diff --git a/Source/postgres/commands/copyConnectionString.ts b/Source/postgres/commands/copyConnectionString.ts index 6d9bcbcf2..716bbd5b6 100644 --- a/Source/postgres/commands/copyConnectionString.ts +++ b/Source/postgres/commands/copyConnectionString.ts @@ -3,56 +3,34 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { - addDatabaseToConnectionString, - copyPostgresConnectionString, -} from "../postgresConnectionStrings"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { checkAuthentication } from "./checkAuthentication"; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; +import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; +import { checkAuthentication } from './checkAuthentication'; -export async function copyConnectionString( - context: IActionContext, - node: PostgresDatabaseTreeItem -): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } +export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString( - parsedCS.hostName, - parsedCS.port, - parsedCS.username, - parsedCS.password, - node.databaseName - ); - } else { - connectionString = addDatabaseToConnectionString( - parsedConnectionString.connectionString, - node.databaseName - ); - } + await checkAuthentication(context, node); + const parsedConnectionString = await node.parent.getFullConnectionString(); + let connectionString: string; + if (node.parent.azureName) { + const parsedCS = await node.parent.getFullConnectionString(); + connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); + } else { + connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); + } - await vscode.env.clipboard.writeText(connectionString); - const message = localize( - "copiedPostgresConnectStringMsg", - "The connection string has been copied to the clipboard" - ); - void vscode.window.showInformationMessage(message); + await vscode.env.clipboard.writeText(connectionString); + const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); + void vscode.window.showInformationMessage(message); } diff --git a/Source/postgres/commands/createPostgresDatabase.ts b/Source/postgres/commands/createPostgresDatabase.ts index c86e5ac45..6c096a52b 100644 --- a/Source/postgres/commands/createPostgresDatabase.ts +++ b/Source/postgres/commands/createPostgresDatabase.ts @@ -3,35 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -import { connectPostgresDatabase } from "./connectPostgresDatabase"; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; +import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; +import { connectPostgresDatabase } from './connectPostgresDatabase'; -export async function createPostgresDatabase( - context: IActionContext, - node?: PostgresServerTreeItem -): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } - const newDatabase: PostgresDatabaseTreeItem = - await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize( - "createPostgresDatabaseMsg", - 'Successfully created database "{0}".', - newDatabase.databaseName - ); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); +export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } + const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); + await connectPostgresDatabase(context, newDatabase); + const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); } diff --git a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts index 64a4fe0b5..81d54b9af 100644 --- a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts @@ -1,3 +1,4 @@ + /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -6,6 +7,6 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; + name?: string; + query?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts index 8b4dd5f93..27b32993c 100644 --- a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts @@ -5,7 +5,6 @@ import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; -export interface IPostgresFunctionQueryWizardContext - extends IPostgresQueryWizardContext { - returnType?: string; +export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { + returnType?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts index ca281d4d4..8c4df098b 100644 --- a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts @@ -11,19 +11,13 @@ import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; -export async function createPostgresFunctionQuery( - context: IActionContext, - treeItem?: PostgresFunctionsTreeItem -): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [ - new FunctionQueryNameStep(), - new FunctionQueryReturnTypeStep(), - ], - executeSteps: [new FunctionQueryCreateStep()], - title: "Create PostgreSQL Function Query", - }); +export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { + const wizardContext: IPostgresFunctionQueryWizardContext = context; + const wizard = new AzureWizard(wizardContext, { + promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], + executeSteps: [new FunctionQueryCreateStep()], + title: 'Create PostgreSQL Function Query' + }); - await runPostgresQueryWizard(wizard, wizardContext, treeItem); + await runPostgresQueryWizard(wizard, wizardContext, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts index 9c0bd1e34..9356882d9 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts @@ -9,26 +9,18 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute( - context: IPostgresFunctionQueryWizardContext - ): Promise { - context.query = defaultFunctionQuery( - nonNullProp(context, "name"), - nonNullProp(context, "returnType") - ); - } + public async execute(context: IPostgresFunctionQueryWizardContext): Promise { + context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultFunctionQuery = ( - name: string, - returnType: string -) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) +const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) RETURNS ${returnType} LANGUAGE plpgsql AS $function$ diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts index a37c18995..cfacc0f64 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts @@ -8,18 +8,11 @@ import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresFunctionQueryWizardContext - ): Promise { - context.returnType = await context.ui.showInputBox({ - prompt: localize( - "provideCustomReturnType", - "Provide custom return type" - ), - }); - } + public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { + context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts index 78459f842..36d798074 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts @@ -9,21 +9,14 @@ import { validateIdentifier } from "../../validateIdentifier"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresFunctionQueryWizardContext - ): Promise { - context.name = ( - await context.ui.showInputBox({ - prompt: localize( - "provideFunctionName", - "Provide function name" - ), - validateInput: validateIdentifier, - }) - ).trim(); - } + public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { + context.name = (await context.ui.showInputBox({ + prompt: localize('provideFunctionName', 'Provide function name'), + validateInput: validateIdentifier + })).trim(); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts index b69c94a2c..63f703793 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts @@ -3,71 +3,48 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzureWizardPromptStep, - IAzureQuickPickItem, - IWizardOptions, -} from "@microsoft/vscode-azext-utils"; +import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresFunctionQueryWizardContext - ): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = - returnTypes.map((r) => { - return { label: r, data: r }; - }); - returnTypeQuickPicks.push({ - label: localize( - "enterCustomReturnType", - "$(pencil) Enter custom return type..." - ), - data: undefined, - }); + public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { + const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); + returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); - context.returnType = ( - await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize("selectReturnType", "Select return type"), - }) - ).data; - } + context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { + placeHolder: localize('selectReturnType', 'Select return type') + })).data; + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } - public async getSubWizard( - context: IPostgresFunctionQueryWizardContext - ): Promise< - IWizardOptions | undefined - > { - return context.returnType - ? undefined - : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } + public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { + return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; + } } // A subset of return types available on pgAdmin const returnTypes: string[] = [ - "bigint", - "bigint[]", - "boolean", - "boolean[]", - "character", - "character[]", - "date", - "date[]", - "integer", - "integer[]", - "json", - "json[]", - "oid", - "oid[]", - "smallint", - "smallint[]", - "text", - "void", + 'bigint', + 'bigint[]', + 'boolean', + 'boolean[]', + 'character', + 'character[]', + 'date', + 'date[]', + 'integer', + 'integer[]', + 'json', + 'json[]', + 'oid', + 'oid[]', + 'smallint', + 'smallint[]', + 'text', + 'void' ]; diff --git a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts index 65288da3d..925695e56 100644 --- a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts @@ -4,31 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { - postgresBaseFileName, - postgresFileExtension, -} from "../../../constants"; +import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from "../../../utils/vscodeUtils"; +import * as vscodeUtil from '../../../utils/vscodeUtils'; import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; import { connectPostgresDatabase } from "../connectPostgresDatabase"; import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; -export async function runPostgresQueryWizard( - wizard: AzureWizard, - context: IPostgresQueryWizardContext, - treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem -): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile( - nonNullProp(context, "query"), - postgresBaseFileName, - postgresFileExtension - ); +export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { + await wizard.prompt(); + await wizard.execute(); + await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } + if (treeItem) { + await connectPostgresDatabase(context, treeItem.parent); + } } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts index b63bf39ae..f1ddbe51b 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts @@ -9,15 +9,12 @@ import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; -export async function createPostgresStoredProcedureQuery( - context: IActionContext, - treeItem?: PostgresStoredProceduresTreeItem -): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: "Create PostgreSQL Stored Procedure Query", - }); +export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { + const wizard = new AzureWizard(context, { + promptSteps: [new StoredProcedureQueryNameStep()], + executeSteps: [new StoredProcedureQueryCreateStep()], + title: 'Create PostgreSQL Stored Procedure Query' + }); - await runPostgresQueryWizard(wizard, context, treeItem); + await runPostgresQueryWizard(wizard, context, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts index 67bbbbf0c..2cf3ef916 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts @@ -9,22 +9,18 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery( - nonNullProp(context, "name") - ); - } + public async execute(context: IPostgresQueryWizardContext): Promise { + context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultStoredProcedureQuery = ( - name: string -) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) +const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) LANGUAGE plpgsql AS $$ BEGIN diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts index 5b694f378..bf9a00392 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts @@ -9,19 +9,14 @@ import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; import { validateIdentifier } from "../../validateIdentifier"; export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = ( - await context.ui.showInputBox({ - prompt: localize( - "provideStoredProcedureName", - "Provide stored procedure name" - ), - validateInput: validateIdentifier, - }) - ).trim(); - } + public async prompt(context: IPostgresQueryWizardContext): Promise { + context.name = (await context.ui.showInputBox({ + prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), + validateInput: validateIdentifier + })).trim(); + } - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts index 94bb16657..9339f6796 100644 --- a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts @@ -6,123 +6,108 @@ import { localize } from "../../../utils/localize"; export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); + // Identifier naming rules: https://aka.ms/AA8618j + identifier = identifier.trim(); - const min = 1; - const max = 63; + const min = 1; + const max = 63; - if (identifier.length < min || identifier.length > max) { - return localize( - "postgresResourcesNameLengthCheck", - "The name must be between {0} and {1} characters.", - min, - max - ); - } + if (identifier.length < min || identifier.length > max) { + return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); + } - if (!identifier[0].match(/[a-z_]/i)) { - return localize( - "mustStartWithLetterOrUnderscore", - "Name must start with a letter or underscore." - ); - } + if (!identifier[0].match(/[a-z_]/i)) { + return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); + } - if (identifier.match(/[^a-z_\d$]/i)) { - return localize( - "canOnlyContainCertainCharacters", - "Name can only contain letters, underscores, digits (0-9), and dollar signs ($)." - ); - } + if (identifier.match(/[^a-z_\d$]/i)) { + return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); + } - if (reservedWords.has(identifier.toLowerCase())) { - return localize( - "cantBeReservedWord", - 'Name cannot be reserved word "{0}".', - identifier - ); - } + if (reservedWords.has(identifier.toLowerCase())) { + return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); + } - return undefined; + return undefined; } // Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html const reservedWords: Set = new Set([ - "all", - "analyse", - "analyze", - "and", - "any", - "array", - "as", - "asc", - "asymmetric", - "both", - "case", - "cast", - "check", - "collate", - "column", - "constraint", - "create", - "current_catalog", - "current_date", - "current_role", - "current_time", - "current_timestamp", - "current_user", - "default", - "deferrable", - "desc", - "distinct", - "do", - "else", - "end", - "except", - "false", - "fetch", - "for", - "foreign", - "from", - "grant", - "group", - "having", - "in", - "initially", - "intersect", - "into", - "lateral", - "leading", - "limit", - "localtime", - "localtimestamp", - "not", - "null", - "offset", - "on", - "only", - "or", - "order", - "placing", - "primary", - "references", - "returning", - "select", - "session_user", - "some", - "symmetric", - "table", - "then", - "to", - "trailing", - "true", - "union", - "unique", - "user", - "using", - "variadic", - "when", - "where", - "window", - "with", + 'all', + 'analyse', + 'analyze', + 'and', + 'any', + 'array', + 'as', + 'asc', + 'asymmetric', + 'both', + 'case', + 'cast', + 'check', + 'collate', + 'column', + 'constraint', + 'create', + 'current_catalog', + 'current_date', + 'current_role', + 'current_time', + 'current_timestamp', + 'current_user', + 'default', + 'deferrable', + 'desc', + 'distinct', + 'do', + 'else', + 'end', + 'except', + 'false', + 'fetch', + 'for', + 'foreign', + 'from', + 'grant', + 'group', + 'having', + 'in', + 'initially', + 'intersect', + 'into', + 'lateral', + 'leading', + 'limit', + 'localtime', + 'localtimestamp', + 'not', + 'null', + 'offset', + 'on', + 'only', + 'or', + 'order', + 'placing', + 'primary', + 'references', + 'returning', + 'select', + 'session_user', + 'some', + 'symmetric', + 'table', + 'then', + 'to', + 'trailing', + 'true', + 'union', + 'unique', + 'user', + 'using', + 'variadic', + 'when', + 'where', + 'window', + 'with' ]); diff --git a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts index cc28cd581..390c1cf42 100644 --- a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts @@ -5,26 +5,20 @@ import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { - AbstractSku, - PostgresAbstractServer, - PostgresServerType, -} from "../../abstract/models"; +import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; -export interface IPostgresServerWizardContext - extends IAzureDBWizardContext, - ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; +export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { + /** + * Username without server, i.e. "user1" + */ + shortUserName?: string; + /** + * Username with server, i.e. "user1@server1" + */ + longUserName?: string; + adminPassword?: string; - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; + server?: PostgresAbstractServer; + sku?: AbstractSku; + serverType?: PostgresServerType; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts index 20d13ffbf..2f07d8203 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts @@ -8,30 +8,24 @@ import { localize } from "../../../../utils/localize"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize("confirmPW", "Confirm your password"); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async ( - value: string | undefined - ): Promise => - await this.validatePassword(context, value), - }); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const prompt: string = localize('confirmPW', 'Confirm your password'); + await context.ui.showInputBox({ + prompt, + password: true, + validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) + }); + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !!context.adminPassword; + } - private async validatePassword( - context: IPostgresServerWizardContext, - passphrase: string | undefined - ): Promise { - if (passphrase !== context.adminPassword) { - return localize("pwMatch", "The passwords must match."); - } + private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { + if (passphrase !== context.adminPassword) { + return localize('pwMatch', 'The passwords must match.'); + } - return undefined; - } + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts index 549f1e67f..f73ce810d 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts @@ -5,133 +5,100 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { - AzureWizardExecuteStep, - callWithMaskHandling, -} from "@microsoft/vscode-azext-utils"; +import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from "vscode"; -import { ext } from "../../../../extensionVariables"; -import { - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../../../../utils/azureClients"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { - AbstractServerCreate, - PostgresServerType, -} from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { Progress } from 'vscode'; +import { ext } from '../../../../extensionVariables'; +import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; + public priority: number = 150; - public async execute( - context: IPostgresServerWizardContext, - progress: Progress<{ message?: string; increment?: number }> - ): Promise { - const locationName: string = ( - await LocationListStep.getLocation(context) - ).name; - const rgName: string = nonNullProp( - nonNullProp(context, "resourceGroup"), - "name" - ); - const size: string = nonNullProp(nonNullProp(context, "sku"), "size"); - const newServerName = nonNullProp(context, "newServerName"); - const password: string = nonNullProp(context, "adminPassword"); + public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - return await callWithMaskHandling(async () => { - const serverType = nonNullProp(context, "serverType"); - const createMessage: string = localize( - "creatingPostgresServer", - 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', - context.newServerName - ); + const locationName: string = (await LocationListStep.getLocation(context)).name; + const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); + const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); + const newServerName = nonNullProp(context, 'newServerName'); + const password: string = nonNullProp(context, 'adminPassword'); - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, "sku"), - administratorLogin: nonNullProp(context, "shortUserName"), - administratorLoginPassword: password, - size: parseInt(size), - }; + return await callWithMaskHandling( + async () => { + const serverType = nonNullProp(context, 'serverType'); + const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = - await createPostgreSQLClient(context); - context.server = - await singleClient.servers.beginCreateAndWait( - rgName, - newServerName, - this.asSingleParameters(options) - ); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = - await createPostgreSQLFlexibleClient(context); - context.server = - await flexiClient.servers.beginCreateAndWait( - rgName, - newServerName, - this.asFlexibleParameters(options) - ); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, password); - } + ext.outputChannel.appendLog(createMessage); + progress.report({ message: createMessage }); + const options: AbstractServerCreate = { + location: locationName, + sku: nonNullProp(context, 'sku'), + administratorLogin: nonNullProp(context, 'shortUserName'), + administratorLoginPassword: password, + size: parseInt(size) + }; - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } + switch (serverType) { + case PostgresServerType.Single: + const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); + context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); + break; + case PostgresServerType.Flexible: + const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); + context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); + break; + } + context.server.serverType = serverType; + context.activityResult = context.server as AppResource; + }, + password); + } - private asFlexibleParameters( - parameters: AbstractServerCreate - ): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size, - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier, - }, - }; - } + public shouldExecute(context: IPostgresServerWizardContext): boolean { + return !context.server; + } + + + private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { + return { + location: parameters.location, + version: "12", + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + storage: { + storageSizeGB: parameters.size + }, + sku: { + name: parameters.sku.name, + tier: parameters.sku.tier + }, + } + } + + private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { + return { + location: parameters.location, + sku: { + name: parameters.sku.name, + capacity: parameters.sku.capacity, + size: parameters.sku.size, + family: parameters.sku.family, + tier: parameters.sku.tier as SingleModels.SkuTier + }, + properties: { + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + sslEnforcement: "Enabled", + createMode: "Default", + version: "11", + storageProfile: { + storageMB: parameters.size + } + } + } + } - private asSingleParameters( - parameters: AbstractServerCreate - ): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier, - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: - parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size, - }, - }, - }; - } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts index dd5c84c25..c48d40c37 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts @@ -3,66 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; -const pwConditionMsg = localize( - "passwordConditionMsg", - "Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.)." -); +const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, "shortUserName"); - context.adminPassword = await context.ui.showInputBox({ - placeHolder: localize("pwPlaceholder", "Administrator Password"), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => - validatePassword(user, password), - }); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const user = nonNullProp(context, 'shortUserName'); + context.adminPassword = (await context.ui.showInputBox({ + placeHolder: localize('pwPlaceholder', 'Administrator Password'), + prompt: pwConditionMsg, + password: true, + validateInput: (password: string) => validatePassword(user, password), + })); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.adminPassword; + } } -async function validatePassword( - username: string, - password: string -): Promise { - password = password ? password : ""; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map((substring) => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize( - "pwLengthCheck", - "Password must be between {0} and {1} characters.", - min, - max - ); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize( - "pwUserSimalarityCheck", - "Password cannot contain the username." - ); - } else { - return undefined; - } +async function validatePassword(username: string, password: string): Promise { + password = password ? password : ''; + + const min = 8; + const max = 128; + + const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; + let numOccurrence = 0; + + regex.map(substring => { + if (password.match(substring)) { + numOccurrence++; + } + }); + + if (password.length < min || password.length > max) { + return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); + } else if (numOccurrence < 3) { + return pwConditionMsg; + } else if (password.includes(username)) { + return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts index 14b7de8f7..7b4890d07 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts @@ -3,80 +3,46 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = ( - await context.ui.showInputBox({ - placeHolder: localize( - "usernamePlaceholder", - "Administrator Username" - ), - validateInput: validateUser, - }) - ).trim(); - const usernameSuffix: string = `@${nonNullProp( - context, - "newServerName" - )}`; - context.longUserName = context.shortUserName + usernameSuffix; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + context.shortUserName = (await context.ui.showInputBox({ + placeHolder: localize('usernamePlaceholder', 'Administrator Username'), + validateInput: validateUser, + })).trim(); + const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; + context.longUserName = context.shortUserName + usernameSuffix; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.shortUserName; + } } async function validateUser(username: string): Promise { - username = username ? username.trim() : ""; + username = username ? username.trim() : ''; - const min = 1; - const max = 63; + const min = 1; + const max = 63; - const restricted = [ - "azure_superuser", - "azure_pg_admin", - "admin", - "administrator", - "root", - "guest", - "public", - ]; + const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; - if (username.length < min || username.length > max) { - return localize( - "usernameLenghtMatch", - "The name must be between {0} and {1} characters.", - min, - max - ); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize( - "usernameCharacterCheck", - 'The name can only contain letters, numbers, and the "_" character.' - ); - } else if (username.match(/^[0-9]+/)) { - return localize( - "usernameBeginningMatch", - "The name cannot start with a number." - ); - } else if (username.toLowerCase().startsWith("pg_")) { - return localize( - "usernameStartWithCheck", - 'Admin username cannot start with "pg_".' - ); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map((d) => `"${d}"`).join(", "); - return localize( - "usernameRestrictedCheck", - "Admin username cannot be any of the following: {0}.", - restrictedString - ); - } else { - return undefined; - } + if (username.length < min || username.length > max) { + return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); + } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { + return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); + } else if (username.match(/^[0-9]+/)) { + return localize('usernameBeginningMatch', 'The name cannot start with a number.'); + } else if (username.toLowerCase().startsWith('pg_')) { + return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); + } else if (restricted.includes(username.toLowerCase())) { + const restrictedString = restricted.map(d => `"${d}"`).join(', '); + return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts index 76b25373e..1af03f5c7 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts @@ -3,111 +3,58 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ResourceGroupListStep, - resourceGroupNamingRules, -} from "@microsoft/vscode-azext-azureutils"; -import { AzureNameStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { - AbstractPostgresClient, - createAbstractPostgresClient, -} from "../../../abstract/AbstractPostgresClient"; -import { - AbstractNameAvailability, - PostgresServerType, -} from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; +import { AzureNameStep } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; +import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerNameStep extends AzureNameStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient( - nonNullProp(context, "serverType"), - context - ); - context.newServerName = ( - await context.ui.showInputBox({ - placeHolder: localize("serverNamePlaceholder", "Server name"), - prompt: localize( - "enterServerNamePrompt", - "Provide a name for the PostgreSQL Server." - ), - validateInput: (name: string) => - validatePostgresServerName( - name, - client, - nonNullProp(context, "serverType") - ), - }) - ).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName( - context, - context.newServerName, - resourceGroupNamingRules - ); - } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable( - context: IPostgresServerWizardContext, - name: string - ): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); + context.newServerName = (await context.ui.showInputBox({ + placeHolder: localize('serverNamePlaceholder', 'Server name'), + prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), + validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) + })).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.newServerName; + } + + protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validatePostgresServerName( - name: string, - client: AbstractPostgresClient, - serverType: PostgresServerType -): Promise { - name = name ? name.trim() : ""; +async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { + name = name ? name.trim() : ''; + + const min = 3; + const max = 63; - const min = 3; - const max = 63; + if (name.length < min || name.length > max) { + return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); + } else if (!(/^[a-z0-9-]+$/).test(name)) { + return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); + } else if (name.startsWith('-') || name.endsWith('-')) { + return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); + } + const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; + const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); - if (name.length < min || name.length > max) { - return localize( - "serverNameLengthCheck", - "The name must be between {0} and {1} characters.", - min, - max - ); - } else if (!/^[a-z0-9-]+$/.test(name)) { - return localize( - "serverNameCharacterCheck", - "Server name must only contain lowercase letters, numbers, and hyphens." - ); - } else if (name.startsWith("-") || name.endsWith("-")) { - return localize( - "serverNamePrefixSuffixCheck", - "Server name must not start or end in a hyphen." - ); - } - const resourceType = - serverType === PostgresServerType.Single - ? "Microsoft.DBforPostgreSQL" - : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = - await client.checkNameAvailability.execute({ - name: name, - type: resourceType, - }); + if (!availability.nameAvailable) { + return availability.message ? + availability.message : + localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); + } - if (!availability.nameAvailable) { - return availability.message - ? availability.message - : localize( - "serverNameAvailabilityCheck", - 'Server name "{0}" is not available.', - name - ); - } + return undefined; - return undefined; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts index e93027936..3431e8f00 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts @@ -3,60 +3,44 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { Progress } from "vscode"; -import { ext } from "../../../../extensionVariables"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { - PostgresAbstractServer, - PostgresServerType, -} from "../../../abstract/models"; -import { setPostgresCredentials } from "../../setPostgresCredentials"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; +import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { Progress } from 'vscode'; +import { ext } from '../../../../extensionVariables'; +import { localize } from '../../../../utils/localize'; +import { nonNullProp } from '../../../../utils/nonNull'; +import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; +import { setPostgresCredentials } from '../../setPostgresCredentials'; +import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; + public priority: number = 200; - public async execute( - context: IPostgresServerWizardContext, - progress: Progress<{ message?: string; increment?: number }> - ): Promise { - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if ( - context.serverType && - context.serverType === PostgresServerType.Single - ) { - user = nonNullProp(context, "longUserName"); - } else { - user = nonNullProp(context, "shortUserName"); - } - const newServerName: string = nonNullProp(context, "newServerName"); + public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const setupMessage: string = localize( - "setupCredentialsMessage", - 'Setting up Credentials for server "{0}"...', - newServerName - ); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, "adminPassword"); - const server: PostgresAbstractServer = nonNullProp(context, "server"); + let user: string; + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexbile Server instance + if (context.serverType && context.serverType === PostgresServerType.Single) { + user = nonNullProp(context, 'longUserName'); + } else { + user = nonNullProp(context, 'shortUserName'); + } + const newServerName: string = nonNullProp(context, 'newServerName'); - await setPostgresCredentials(user, password, nonNullProp(server, "id")); - const completedMessage: string = localize( - "addedCredentialsMessage", - 'Successfully setup credentials for server "{0}".', - newServerName - ); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } + const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); + progress.report({ message: setupMessage }); + ext.outputChannel.appendLog(setupMessage); + const password: string = nonNullProp(context, 'adminPassword'); + const server: PostgresAbstractServer = nonNullProp(context, 'server'); - public shouldExecute(): boolean { - return true; - } + await setPostgresCredentials(user, password, nonNullProp(server, 'id')); + const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + } + + public shouldExecute(): boolean { + return true; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts index 3efe5e223..654cd0430 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts @@ -2,10 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzureWizardPromptStep, - IAzureQuickPickItem, -} from "@microsoft/vscode-azext-utils"; +import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../utils/localize"; import { nonNullProp } from "../../../../utils/nonNull"; import { openUrl } from "../../../../utils/openUrl"; @@ -13,257 +10,241 @@ import { AbstractSku, PostgresServerType } from "../../../abstract/models"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; + label: string; + description: string; + sku: AbstractSku; + group?: string; } export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = - await this.getPicks(nonNullProp(context, "serverType")); - pricingTiers.push({ - label: localize( - "ShowPricingCalculator", - "$(link-external) Show pricing information..." - ), - onPicked: async () => { - await openUrl("https://aka.ms/AAcxhvm"); - }, - data: undefined, - }); + public async prompt( + context: IPostgresServerWizardContext + ): Promise { + const placeHolder: string = localize( + "selectPostgresSku", + "Select the Postgres SKU and options." + ); + const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); + pricingTiers.push({ + label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), + onPicked: async () => { + await openUrl('https://aka.ms/AAcxhvm'); + }, data: undefined + }); - context.sku = ( - await context.ui.showQuickPick(pricingTiers, { - placeHolder, - suppressPersistence: true, - enableGrouping: true, - }) - ).data; - } + context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return context.sku === undefined; + } - public async getPicks( - serverType: PostgresServerType - ): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = - serverType === PostgresServerType.Single - ? singleServerSkus - : flexibleServerSkus; + public async getPicks(serverType: PostgresServerType): Promise[]> { + const options: IAzureQuickPickItem[] = []; + const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: - option.group || - localize("addlOptions", "Additional Options"), - }); - }); - return options; - } + skuOptions.forEach((option) => { + options.push({ + label: option.label, + description: localize( + nonNullProp(option.sku, "name"), + option.description + ), + data: option.sku, + group: option.group || localize('addlOptions', 'Additional Options') + }); + }); + return options; + } } -const recommendedGroup = localize("recommendGroup", "Recommended"); +const recommendedGroup = localize('recommendGroup', 'Recommended'); const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup, - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup, - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, + { + label: "B1", + description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", + sku: { + name: "B_Gen5_1", + tier: "Basic", + capacity: 1, + family: "Gen5", + size: "5120", + }, + group: recommendedGroup + }, + { + label: "B2", + description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", + sku: { + name: "B_Gen5_2", + tier: "Basic", + capacity: 2, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP2", + description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_2", + tier: "GeneralPurpose", + capacity: 2, + family: "Gen5", + size: "51200", + }, + group: recommendedGroup + }, + { + label: "GP4", + description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_4", + tier: "GeneralPurpose", + capacity: 4, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP8", + description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_8", + tier: "GeneralPurpose", + capacity: 8, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP16", + description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_16", + tier: "GeneralPurpose", + capacity: 16, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP32", + description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_32", + tier: "GeneralPurpose", + capacity: 32, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP64", + description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_64", + tier: "GeneralPurpose", + capacity: 64, + family: "Gen5", + size: "204800", + }, + }, ]; // Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 // See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup, - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup, - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, + { + label: "B1ms", + description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", + sku: { + name: "Standard_B1ms", + tier: "Burstable", + capacity: 1, + size: "32", + }, + group: recommendedGroup + }, + { + label: "B2s", + description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", + sku: { + name: "Standard_B2s", + tier: "Burstable", + capacity: 2, + size: "32", + }, + }, + { + label: "D2s_v3", + description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", + sku: { + name: "Standard_D2s_v3", + tier: "GeneralPurpose", + capacity: 2, + size: "32", + }, + group: recommendedGroup + }, + { + label: "D4s_v3", + description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", + sku: { + name: "Standard_D4s_v3", + tier: "GeneralPurpose", + capacity: 4, + size: "32", + }, + }, + { + label: "D8s_v3", + description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", + sku: { + name: "Standard_D8s_v3", + tier: "GeneralPurpose", + capacity: 8, + size: "64", + }, + }, + { + label: "D16s_v3", + description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", + sku: { + name: "Standard_D16s_v3", + tier: "GeneralPurpose", + capacity: 16, + size: "64", + }, + }, + { + label: "D32s_v3", + description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", + sku: { + name: "Standard_D32s_v3", + tier: "GeneralPurpose", + capacity: 32, + size: "64", + }, + }, + { + label: "D48s_v3", + description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", + sku: { + name: "Standard_D48s_v3", + tier: "GeneralPurpose", + capacity: 48, + size: "256", + }, + }, + { + label: "D64s_v3", + description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", + sku: { + name: "Standard_D64s_v3", + tier: "GeneralPurpose", + capacity: 64, + size: "256", + }, + }, ]; diff --git a/Source/postgres/commands/deletePostgresDatabase.ts b/Source/postgres/commands/deletePostgresDatabase.ts index 705b8823f..a09520bde 100644 --- a/Source/postgres/commands/deletePostgresDatabase.ts +++ b/Source/postgres/commands/deletePostgresDatabase.ts @@ -3,51 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function deletePostgresDatabase( - context: IActionContext, - node?: PostgresDatabaseTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } - const message: string = localize( - "deletesPostgresDatabase", - 'Are you sure you want to delete database "{0}"?', - node.databaseName - ); - const result = await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresDatabase" }, - DialogResponses.deleteResponse - ); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize( - "deletePostgresDatabaseMsg", - 'Successfully deleted database "{0}".', - node.databaseName - ); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } + const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); + const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); + if (result === DialogResponses.deleteResponse) { + await node.deleteTreeItem(context); + } + const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresFunction.ts b/Source/postgres/commands/deletePostgresFunction.ts index 9ee7a21d7..9a4547428 100644 --- a/Source/postgres/commands/deletePostgresFunction.ts +++ b/Source/postgres/commands/deletePostgresFunction.ts @@ -3,50 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { window } from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import { window } from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function deletePostgresFunction( - context: IActionContext, - treeItem?: PostgresFunctionTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - { ...context, suppressCreatePick: true }, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresFunctionTreeItem.contextValue, - } - ); - } +export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresFunctionTreeItem.contextValue + }); + } - const message: string = localize( - "deleteFunction", - 'Are you sure you want to delete function "{0}"?', - treeItem.label - ); - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresFunction" }, - DialogResponses.deleteResponse - ); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize( - "successfullyDeletedFunction", - 'Successfully deleted function "{0}".', - treeItem.label - ); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresServer.ts b/Source/postgres/commands/deletePostgresServer.ts index 686b3c134..733c6fca6 100644 --- a/Source/postgres/commands/deletePostgresServer.ts +++ b/Source/postgres/commands/deletePostgresServer.ts @@ -3,29 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { deleteDatabaseAccount } from "../../commands/deleteDatabaseAccount/deleteDatabaseAccount"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; +import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; +import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -export async function deletePostgresServer( - context: IActionContext, - node?: PostgresServerTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } +export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } - await deleteDatabaseAccount(context, node, true); + await deleteDatabaseAccount(context, node, true) } diff --git a/Source/postgres/commands/deletePostgresStoredProcedure.ts b/Source/postgres/commands/deletePostgresStoredProcedure.ts index 244a207d2..6abece79b 100644 --- a/Source/postgres/commands/deletePostgresStoredProcedure.ts +++ b/Source/postgres/commands/deletePostgresStoredProcedure.ts @@ -3,51 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { window } from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import { window } from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; +import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; -export async function deletePostgresStoredProcedure( - context: IActionContext, - treeItem?: PostgresStoredProcedureTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = - await ext.rgApi.pickAppResource( - { ...context, suppressCreatePick: true }, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresStoredProcedureTreeItem.contextValue, - } - ); - } +export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue + }); + } - const message: string = localize( - "deleteStoredProcedure", - 'Are you sure you want to delete stored procedure "{0}"?', - treeItem.label - ); - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresStoredProcedure" }, - DialogResponses.deleteResponse - ); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize( - "successfullyDeletedStoredProcedure", - 'Successfully deleted stored procedure "{0}".', - treeItem.label - ); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresTable.ts b/Source/postgres/commands/deletePostgresTable.ts index 60cfb0c18..bfdce33a2 100644 --- a/Source/postgres/commands/deletePostgresTable.ts +++ b/Source/postgres/commands/deletePostgresTable.ts @@ -3,48 +3,26 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - DialogResponses, - IActionContext, - ITreeItemPickerContext, -} from "@microsoft/vscode-azext-utils"; -import { window } from "vscode"; +import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; +import { window } from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; -export async function deletePostgresTable( - context: IActionContext, - node?: PostgresTableTreeItem -): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource( - { ...context, suppressCreatePick: true }, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue, - } - ); - } - const message: string = localize( - "deletesPostgresTable", - 'Are you sure you want to delete table "{0}"?', - node.label - ); - await context.ui.showWarningMessage( - message, - { modal: true, stepName: "deletePostgresTable" }, - DialogResponses.deleteResponse - ); - await node.deleteTreeItem(context); - const deleteMessage: string = localize( - "successfullyDeletedTable", - 'Successfully deleted table "{0}".', - node.label - ); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresTableTreeItem.contextValue + }); + } + const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); + await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); + await node.deleteTreeItem(context); + const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/enterPostgresCredentials.ts b/Source/postgres/commands/enterPostgresCredentials.ts index ff146d290..aa993c337 100644 --- a/Source/postgres/commands/enterPostgresCredentials.ts +++ b/Source/postgres/commands/enterPostgresCredentials.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; +import * as vscode from 'vscode'; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { PostgresServerType } from "../abstract/models"; +import { nonNullProp } from '../../utils/nonNull'; +import { PostgresServerType } from '../abstract/models'; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; import { setPostgresCredentials } from "./setPostgresCredentials"; @@ -17,118 +17,69 @@ import { setPostgresCredentials } from "./setPostgresCredentials"; * Get the username and password for the Postgres database from user input. */ async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string; password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize( - "enterUsername", - 'Enter username for server "{0}"', - serverDisplayName - ), - stepName: "enterPostgresUsername", - validateInput: (value: string) => { - return value && value.length - ? undefined - : localize( - "usernameCannotBeEmpty", - "Username cannot be empty." - ); - }, - }); + context: IActionContext, + serverType: PostgresServerType, + serverName: string, + serverDisplayName: string +): Promise<{ username: string, password: string }> { + let username: string = await context.ui.showInputBox({ + prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), + stepName: 'enterPostgresUsername', + validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } + }); - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if ( - serverType === PostgresServerType.Single && - !username.includes(usernameSuffix) - ) { - username += usernameSuffix; - } + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexible Server instance + const usernameSuffix: string = `@${serverName}`; + if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { + username += usernameSuffix; + } - const password: string = await context.ui.showInputBox({ - prompt: localize( - "enterPassword", - 'Enter password for server "{0}"', - serverDisplayName - ), - stepName: "enterPostgresPassword", - password: true, - validateInput: (value: string) => { - return value && value.length - ? undefined - : localize( - "passwordCannotBeEmpty", - "Password cannot be empty." - ); - }, - }); + const password: string = await context.ui.showInputBox({ + prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), + stepName: 'enterPostgresPassword', + password: true, + validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } + }); - return { username, password }; + return { username, password }; } /** * Save the username and password in secure local storage. */ -async function persistUsernamePassword( - id: string, - serverName: string, - username: string, - password: string -): Promise { - const progressMessage: string = localize( - "setupCredentialsMessage", - 'Setting up credentials for server "{0}"...', - serverName - ); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage, - }; +async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { + const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage + }; - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); + await vscode.window.withProgress(options, async () => { + await setPostgresCredentials(username, password, id); + }); - const completedMessage: string = localize( - "setupCredentialsMessage", - 'Successfully added credentials to server "{0}".', - serverName - ); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); + const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); } -export async function enterPostgresCredentials( - context: IActionContext, - treeItem?: PostgresServerTreeItem -): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - } - ); - } +export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter] + }); + } - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, "azureName"); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, "id"); + const serverType = treeItem.serverType; + const serverName: string = nonNullProp(treeItem, 'azureName'); + const serverDisplayName: string = treeItem.label; + const id: string = nonNullProp(treeItem, 'id'); - const { username, password } = await getUsernamePassword( - context, - serverType, - serverName, - serverDisplayName - ); + const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); - await persistUsernamePassword(id, serverName, username, password); + await persistUsernamePassword(id, serverName, username, password); - treeItem.setCredentials(username, password); - await treeItem.refresh(context); + treeItem.setCredentials(username, password); + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/executePostgresQueryInDocument.ts b/Source/postgres/commands/executePostgresQueryInDocument.ts index 4aedb847b..af5d3ca5e 100644 --- a/Source/postgres/commands/executePostgresQueryInDocument.ts +++ b/Source/postgres/commands/executePostgresQueryInDocument.ts @@ -3,92 +3,63 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { EOL } from "os"; -import * as path from "path"; -import { ClientConfig, QueryResult } from "pg"; -import * as vscode from "vscode"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import * as vscodeUtil from "../../utils/vscodeUtils"; -import { runPostgresQuery } from "../runPostgresQuery"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { checkAuthentication } from "./checkAuthentication"; -import { loadPersistedPostgresDatabase } from "./registerPostgresCommands"; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import { EOL } from 'os'; +import * as path from 'path'; +import { ClientConfig, QueryResult } from 'pg'; +import * as vscode from 'vscode'; +import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import * as vscodeUtil from '../../utils/vscodeUtils'; +import { runPostgresQuery } from '../runPostgresQuery'; +import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; +import { checkAuthentication } from './checkAuthentication'; +import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; -export async function executePostgresQueryInDocument( - context: IActionContext -): Promise { - await loadPersistedPostgresDatabase(); +export async function executePostgresQueryInDocument(context: IActionContext): Promise { + await loadPersistedPostgresDatabase(); - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresDatabaseTreeItem.contextValue, - } - ); - } + let treeItem: PostgresDatabaseTreeItem; + if (ext.connectedPostgresDB) { + treeItem = ext.connectedPostgresDB; + } else { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresDatabaseTreeItem.contextValue + }); + } - const clientConfig: ClientConfig = await checkAuthentication( - context, - treeItem - ); + const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); - const activeEditor: vscode.TextEditor | undefined = - vscode.window.activeTextEditor; + const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - if (!activeEditor?.document) { - throw new Error( - localize( - "openQueryBeforeExecuting", - "Open a PostgreSQL query before executing." - ) - ); - } + if (!activeEditor?.document) { + throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); + } - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery( - clientConfig, - query - ); - ext.outputChannel.appendLine( - localize( - "executedQuery", - 'Successfully executed "{0}" query.', - queryResult.command - ) - ); + const query: string | undefined = activeEditor.document.getText(); + const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); + ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); - if (queryResult.rowCount) { - const fileExtension: string = path.extname( - activeEditor.document.fileName - ); - const queryFileName: string = path.basename( - activeEditor.document.fileName, - fileExtension - ); - const outputFileName: string = `${queryFileName}-output`; + if (queryResult.rowCount) { + const fileExtension: string = path.extname(activeEditor.document.fileName); + const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); + const outputFileName: string = `${queryFileName}-output`; - const fields: string[] = queryResult.fields.map((f) => f.name); - let csvData: string = `${fields.join(",")}${EOL}`; + const fields: string[] = queryResult.fields.map(f => f.name); + let csvData: string = `${fields.join(',')}${EOL}`; - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(",")}${EOL}`; - } + for (const row of queryResult.rows) { + const fieldValues: string[] = []; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + fieldValues.push(row[field]); + } + csvData += `${fieldValues.join(',')}${EOL}`; + } - await vscodeUtil.showNewFile(csvData, outputFileName, ".csv"); - } - await treeItem.refresh(context); + await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); + } + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/openPostgresFunction.ts b/Source/postgres/commands/openPostgresFunction.ts index 4b186ed71..26103970f 100644 --- a/Source/postgres/commands/openPostgresFunction.ts +++ b/Source/postgres/commands/openPostgresFunction.ts @@ -9,20 +9,13 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function openPostgresFunction( - context: IActionContext, - treeItem?: PostgresFunctionTreeItem -): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresFunctionTreeItem.contextValue, - } - ); - } +export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresFunctionTreeItem.contextValue + }); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/openPostgresStoredProcedure.ts b/Source/postgres/commands/openPostgresStoredProcedure.ts index 1eb8931aa..3c98ff743 100644 --- a/Source/postgres/commands/openPostgresStoredProcedure.ts +++ b/Source/postgres/commands/openPostgresStoredProcedure.ts @@ -9,21 +9,13 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function openPostgresStoredProcedure( - context: IActionContext, - treeItem?: PostgresStoredProcedureTreeItem -): Promise { - if (!treeItem) { - treeItem = - await ext.rgApi.pickAppResource( - context, - { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: - PostgresStoredProcedureTreeItem.contextValue, - } - ); - } +export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource(context, { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue + }); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/registerPostgresCommands.ts b/Source/postgres/commands/registerPostgresCommands.ts index 89412a2ba..b861e00f7 100644 --- a/Source/postgres/commands/registerPostgresCommands.ts +++ b/Source/postgres/commands/registerPostgresCommands.ts @@ -3,19 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, - registerCommandWithTreeNodeUnwrapping, -} from "@microsoft/vscode-azext-utils"; +import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; import { defaults } from "pg"; import { languages } from "vscode"; -import { - connectedPostgresKey, - doubleClickDebounceDelay, - postgresDefaultDatabase, - postgresLanguageId, -} from "../../constants"; +import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; import { ext } from "../../extensionVariables"; import { openUrl } from "../../utils/openUrl"; import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; @@ -37,126 +28,55 @@ import { openPostgresFunction } from "./openPostgresFunction"; import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push( - languages.registerCodeLensProvider( - postgresLanguageId, - ext.postgresCodeLensProvider - ) - ); + ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); + ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); - void loadPersistedPostgresDatabase(); + void loadPersistedPostgresDatabase(); - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; + //update defaults.database of 'pg' + defaults.database = postgresDefaultDatabase; - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteServer", - deletePostgresServer - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.enterCredentials", - enterPostgresCredentials - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.configureFirewall", - configurePostgresFirewall - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.createDatabase", - createPostgresDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteDatabase", - deletePostgresDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteTable", - deletePostgresTable - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.openFunction", - openPostgresFunction, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.openStoredProcedure", - openPostgresStoredProcedure, - doubleClickDebounceDelay - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteFunction", - deletePostgresFunction - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.deleteStoredProcedure", - deletePostgresStoredProcedure - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.connectDatabase", - connectPostgresDatabase - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.createFunctionQuery", - createPostgresFunctionQuery - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.createStoredProcedureQuery", - createPostgresStoredProcedureQuery - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.executeQuery", - executePostgresQueryInDocument - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.copyConnectionString", - copyConnectionString - ); - registerCommandWithTreeNodeUnwrapping( - "postgreSQL.showPasswordlessWiki", - showPasswordlessWiki - ); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); + registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); + registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); + registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); + registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); + registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); + registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); + registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); + registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); + registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); + registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); + registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); } export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling( - "postgreSQL.loadPersistedDatabase", - async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = "true"; + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = 'true'; - try { - const persistedTreeItemId: string | undefined = - ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: - | PostgresDatabaseTreeItem - | undefined = ( - await ext.rgApi.appResourceTree.findTreeItem( - persistedTreeItemId, - context - ) - ); - if (persistedTreeItem) { - await connectPostgresDatabase( - context, - persistedTreeItem - ); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase( - undefined - ); - } - } - } - ); + try { + const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); + if (persistedTreeItemId) { + const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); + if (persistedTreeItem) { + await connectPostgresDatabase(context, persistedTreeItem); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(undefined); + } + } + }); } export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); + await openUrl("https://aka.ms/postgresql-passwordless-wiki"); } diff --git a/Source/postgres/commands/setPostgresCredentials.ts b/Source/postgres/commands/setPostgresCredentials.ts index 2807acc3c..8df8260f6 100644 --- a/Source/postgres/commands/setPostgresCredentials.ts +++ b/Source/postgres/commands/setPostgresCredentials.ts @@ -8,37 +8,25 @@ import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } -export async function setPostgresCredentials( - username: string, - password: string, - serverId: string -): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = - ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue - ? JSON.parse(storedValue) - : []; +export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { - return server.id !== serverId; - }); + // Remove this server from the cache if it's there + servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); - const newServer: IPersistedServer = { - id: serverId, - username, - }; + const newServer: IPersistedServer = { + id: serverId, + username + }; - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store( - getSecretStorageKey(serviceName, serverId), - password - ); + servers.push(newServer); + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); } diff --git a/Source/postgres/getClientConfig.ts b/Source/postgres/getClientConfig.ts index 431a95bea..bdc545945 100644 --- a/Source/postgres/getClientConfig.ts +++ b/Source/postgres/getClientConfig.ts @@ -8,15 +8,12 @@ import { ConnectionOptions } from "tls"; import { postgresDefaultPort } from "../constants"; import { nonNullProp } from "../utils/nonNull"; import { PostgresServerType } from "./abstract/models"; -import { - ParsedPostgresConnectionString, - addDatabaseToConnectionString, -} from "./postgresConnectionStrings"; +import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; + password: ClientConfig | undefined; + azureAd: ClientConfig | undefined; + connectionString: ClientConfig | undefined; }; export type PostgresClientConfigType = keyof PostgresClientConfigs; @@ -24,133 +21,82 @@ export type PostgresClientConfigType = keyof PostgresClientConfigs; * Test if the database can be connected to using the given client config. * @throws if the client failed to connect to the database. */ -export async function testClientConfig( - clientConfig: ClientConfig -): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } +export async function testClientConfig(clientConfig: ClientConfig): Promise { + const client = new Client(clientConfig); + try { + await client.connect(); + } finally { + await client.end(); + } } -async function getConnectionStringClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - databaseName: string -): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString( - connectionString, - databaseName - ); - } - return { connectionString: connectionString }; +async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { + let connectionString = parsedConnectionString.connectionString; + if (!parsedConnectionString.databaseName) { + connectionString = addDatabaseToConnectionString(connectionString, databaseName); + } + return { connectionString: connectionString }; } -async function getUsernamePasswordClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string -): Promise { - const host = nonNullProp(parsedConnectionString, "hostName"); - const port: number = parsedConnectionString.port - ? parseInt(parsedConnectionString.port) - : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; +async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { + const host = nonNullProp(parsedConnectionString, 'hostName'); + const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); + const username: string | undefined = parsedConnectionString.username; + const password: string | undefined = parsedConnectionString.password; - if (!!username && !!password && !!host && !!port) { - return { - user: username, - password, - ssl: sslAzure, - host, - port, - database: databaseName, - }; - } else { - return undefined; - } + if (!!username && !!password && !!host && !!port) { + return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; + } else { + return undefined; + } } async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string, + azureAdUserId: string, + getToken: () => Promise ): Promise { - const host = nonNullProp(parsedConnectionString, "hostName"); - const port: number = parsedConnectionString.port - ? parseInt(parsedConnectionString.port) - : parseInt(postgresDefaultPort); - return { - user: azureAdUserId, - password: getToken, - ssl: sslAzure, - host, - port, - database: databaseName, - }; + const host = nonNullProp(parsedConnectionString, 'hostName'); + const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); + return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; } export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + serverType: PostgresServerType, + hasSubscription: boolean, + databaseName: string, + azureUserId?: string, + getToken?: () => Promise ): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined, - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: - serverType === PostgresServerType.Single - ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] - : [DigiCertGlobalRootCA], - }; - const passwordClientConfig = await getUsernamePasswordClientConfig( - parsedConnectionString, - sslAzure, - databaseName - ); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if ( - serverType === PostgresServerType.Flexible && - !!azureUserId && - !!getToken - ) { - const azureAdClientConfig = await getAzureAdClientConfig( - parsedConnectionString, - sslAzure, - databaseName, - azureUserId, - getToken - ); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = - await getConnectionStringClientConfig( - parsedConnectionString, - databaseName - ); - clientConfigs.connectionString = connectionStringClientConfig; - } + const clientConfigs: PostgresClientConfigs = { + password: undefined, + azureAd: undefined, + connectionString: undefined + }; + if (hasSubscription) { + const sslAzure: ConnectionOptions = { + // Always provide the certificate since it is accepted even when SSL is disabled + // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) + // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 + ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] + }; + const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); + if (passwordClientConfig) { + clientConfigs.password = passwordClientConfig; + } + if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { + const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); + clientConfigs.azureAd = azureAdClientConfig; + } + } else { + const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); + clientConfigs.connectionString = connectionStringClientConfig; + } - return clientConfigs; + return clientConfigs; } // Postgres Single Server Root Cert, https://aka.ms/AA7wnvl @@ -223,3 +169,4 @@ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE-----`; + diff --git a/Source/postgres/getPostgresProcedureQueryRows.ts b/Source/postgres/getPostgresProcedureQueryRows.ts index 0cecca979..ad791ff2e 100644 --- a/Source/postgres/getPostgresProcedureQueryRows.ts +++ b/Source/postgres/getPostgresProcedureQueryRows.ts @@ -9,16 +9,16 @@ import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; + schema: string; + name: string; + oid: number; + args: string; + definition: string; } function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, + // Adapted from https://aka.ms/AA83fg8 + return `select n.nspname as schema, p.proname as name, p.oid as oid, pg_get_function_arguments(p.oid) as args, @@ -33,37 +33,26 @@ function getProceduresQuery(conditions: string): string { order by name;`; } -export async function getPostgresProcedureQueryRows( - treeItem: PostgresResourcesTreeItemBase -): Promise { - let conditions: string; +export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { + let conditions: string; - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${ - (await treeItem.parent.parent.supportsStoredProcedures( - treeItem.clientConfig - )) - ? "and p.prokind = 'f'" - : "" - }`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } + if (treeItem instanceof PostgresFunctionsTreeItem) { + conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') + ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; + } else { + // Assume stored procedures + conditions = "and p.prokind = 'p'"; + } - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery( - treeItem.clientConfig, - query - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; + const query: string = getProceduresQuery(conditions); + const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } + treeItem.resourcesAndSchemas = {}; + for (const row of rows) { + treeItem.addResourcesAndSchemasEntry(row.name, row.schema); + } - return rows; + return rows; } diff --git a/Source/postgres/getTables.ts b/Source/postgres/getTables.ts index e74d1074d..ebc7d1c75 100644 --- a/Source/postgres/getTables.ts +++ b/Source/postgres/getTables.ts @@ -7,10 +7,10 @@ import { ClientConfig, QueryResult } from "pg"; import { runPostgresQuery } from "./runPostgresQuery"; export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; + schemaName: string; + name: string; + oid: string; + columnNames: string[]; } const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, @@ -23,22 +23,12 @@ const tablesQuery: string = `select schemaname, tablename, array_agg (columnname where schemaname != 'pg_catalog' AND schemaname != 'information_schema' group by schemaname, tablename;`; -export async function getTables( - clientConfig: ClientConfig -): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery( - clientConfig, - tablesQuery - ); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ - schemaName: row.schemaname, - name: row.tablename, - oid: row.oid, - columnNames: row.columnnames, - }); - } - return tablesArray; +export async function getTables(clientConfig: ClientConfig): Promise { + const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); + const tablesArray: IPostgresTable[] = []; + for (const row of tableInfoRows.rows) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); + } + return tablesArray; } diff --git a/Source/postgres/postgresConnectionStrings.ts b/Source/postgres/postgresConnectionStrings.ts index f1c46e6e7..ea9ce9e2e 100644 --- a/Source/postgres/postgresConnectionStrings.ts +++ b/Source/postgres/postgresConnectionStrings.ts @@ -8,84 +8,67 @@ import { postgresDefaultPort } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; import { nonNullProp } from "../utils/nonNull"; -export function parsePostgresConnectionString( - connectionString: string -): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); +export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { + const config: ConnectionOptions = parse(connectionString.trim()); + return new ParsedPostgresConnectionString(connectionString, config); } -export function addDatabaseToConnectionString( - connectionString: string, - databaseName: string -): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); +export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { + const url = new URL(connectionString); + url.pathname = encodeURIComponent(databaseName); + return url.toString(); } -export function createPostgresConnectionString( - hostName: string, - port: string = postgresDefaultPort, - username?: string | undefined, - password?: string | undefined, - databaseName?: string | undefined -): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + connectionString += `${encodedUsername}:${encodedPassword}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } -export function copyPostgresConnectionString( - hostName: string, - port: string = postgresDefaultPort, - username?: string | undefined, - password?: string | undefined, - databaseName?: string | undefined -): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; + connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; + public readonly hostName: string; + public username: string | undefined; + public password: string | undefined; + public readonly port: string; - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, "host"); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } + constructor(connectionString: string, config: ConnectionOptions) { + super(connectionString, config.database ? config.database : undefined); + this.hostName = nonNullProp(config, 'host'); + this.port = config.port ? config.port : `${postgresDefaultPort}`; + this.username = config.user; + this.password = config.password; + } } diff --git a/Source/postgres/postgresConstants.ts b/Source/postgres/postgresConstants.ts index f94f58a25..9bcf15144 100644 --- a/Source/postgres/postgresConstants.ts +++ b/Source/postgres/postgresConstants.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const invalidCredentialsErrorType: string = "28P01"; -export const firewallNotConfiguredErrorType: string = "28000"; -export const timeoutErrorType = "ETIMEDOUT"; +export const invalidCredentialsErrorType: string = '28P01'; +export const firewallNotConfiguredErrorType: string = '28000'; +export const timeoutErrorType = 'ETIMEDOUT'; diff --git a/Source/postgres/runPostgresQuery.ts b/Source/postgres/runPostgresQuery.ts index ce2a67c7b..b7d325364 100644 --- a/Source/postgres/runPostgresQuery.ts +++ b/Source/postgres/runPostgresQuery.ts @@ -5,18 +5,15 @@ import { Client, ClientConfig, QueryResult } from "pg"; -export async function runPostgresQuery( - clientConfig: ClientConfig, - query: string -): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } +export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { + const client: Client = new Client(clientConfig); + try { + await client.connect(); + return await client.query(query); + } finally { + await client.end(); + } } export function wrapArgInQuotes(input: string): string { - return `"${input}"`; + return `"${input}"`; } diff --git a/Source/postgres/services/PostgresCodeLensProvider.ts b/Source/postgres/services/PostgresCodeLensProvider.ts index d0d6bfe39..5d075eb3c 100644 --- a/Source/postgres/services/PostgresCodeLensProvider.ts +++ b/Source/postgres/services/PostgresCodeLensProvider.ts @@ -3,88 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import { - CodeLens, - CodeLensProvider, - Event, - EventEmitter, - Position, - ProviderResult, - Range, -} from "vscode"; +import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; import { localize } from "../../utils/localize"; export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: EventEmitter = new EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling( - "postgreSQL.provideCodeLenses", - (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(): ProviderResult { + return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: CodeLens[] = []; - let title: string; - if (!isInitialized) { - title = localize("initializing", "Initializing..."); - } else if (isConnected) { - title = localize( - "connectedToDatabase", - 'Connected to "{0}"', - database - ); - } else { - title = localize( - "connectToDatabase", - "Connect to a database" - ); - } + let title: string; + if (!isInitialized) { + title = localize('initializing', 'Initializing...'); + } else if (isConnected) { + title = localize('connectedToDatabase', 'Connected to "{0}"', database); + } else { + title = localize('connectToDatabase', 'Connect to a database'); + } - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && "postgreSQL.connectDatabase", - }, - range: new Range(new Position(0, 0), new Position(0, 0)), - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title, + command: isInitialized && 'postgreSQL.connectDatabase' + }, + range: new Range(new Position(0, 0), new Position(0, 0)) + }); - if (isConnected) { - lenses.push({ - command: { - title: "Execute Query", - command: "postgreSQL.executeQuery", - }, - range: new Range( - new Position(0, 0), - new Position(0, 0) - ), - }); - } + if (isConnected) { + lenses.push({ + command: { + title: 'Execute Query', + command: 'postgreSQL.executeQuery' + }, + range: new Range(new Position(0, 0), new Position(0, 0)) + }); + } - return lenses; - } - ); - } + return lenses; + }); + } } diff --git a/Source/postgres/showPostgresQuery.ts b/Source/postgres/showPostgresQuery.ts index 4d1b277b4..7d6e2aa1d 100644 --- a/Source/postgres/showPostgresQuery.ts +++ b/Source/postgres/showPostgresQuery.ts @@ -3,18 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { postgresBaseFileName, postgresFileExtension } from "../constants"; -import * as vscodeUtil from "../utils/vscodeUtils"; +import { postgresBaseFileName, postgresFileExtension } from '../constants'; +import * as vscodeUtil from '../utils/vscodeUtils'; import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; -export async function showPostgresQuery( - treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem -): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile( - treeItem.definition, - fileName, - postgresFileExtension - ); +export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { + const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; + await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); } diff --git a/Source/postgres/tree/ClientConfigFactory.ts b/Source/postgres/tree/ClientConfigFactory.ts index 67a00710c..271f5b92f 100644 --- a/Source/postgres/tree/ClientConfigFactory.ts +++ b/Source/postgres/tree/ClientConfigFactory.ts @@ -3,123 +3,84 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - callWithTelemetryAndErrorHandling, - parseError, -} from "@microsoft/vscode-azext-utils"; +import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { - getAzureAdUserSession, - getTokenFunction, -} from "../../azureAccountUtils"; +import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; import { localize } from "../../utils/localize"; -import { - PostgresClientConfigType, - getClientConfigs, - testClientConfig, -} from "../getClientConfig"; -import { - firewallNotConfiguredErrorType, - invalidCredentialsErrorType, - timeoutErrorType, -} from "../postgresConstants"; +import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; +import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -export const postgresResourceType = - "https://ossrdbms-aad.database.windows.net/"; +export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; /** * Creates an object that can be used to execute a postgres query with connection test and telemetry. */ export class PostgresClientConfigFactory { - public static async getClientConfigFromNode( - treeItem: PostgresServerTreeItem, - databaseName: string - ): Promise<{ - type: "azureAd" | "password" | "connectionString"; - clientConfig: ClientConfig; - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); + public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ + type: "azureAd" | "password" | "connectionString", + clientConfig: ClientConfig + }> { + const parsedConnectionString = await treeItem.getFullConnectionString(); + const azureUserSession = await getAzureAdUserSession(); - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction( - subscription.credentials, - postgresResourceType - ); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); + let hasSubscription: boolean = false; + let tokenFunction: (() => Promise) | undefined = undefined; + try { + const subscription = treeItem.subscription; + hasSubscription = true; + tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); + } catch (error) { + hasSubscription = false; + } + const clientConfigs = await getClientConfigs( + parsedConnectionString, + treeItem.serverType, + hasSubscription, + databaseName, + azureUserSession?.userId, + tokenFunction + ); - const clientConfigTypeOrder: PostgresClientConfigType[] = [ - "azureAd", - "password", - "connectionString", - ]; + const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = - clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } + for (const clientConfigType of clientConfigTypeOrder) { + const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; + if (!clientConfig) { + continue; + } - try { - await callWithTelemetryAndErrorHandling( - "postgreSQL.testClientConfig", - async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = - clientConfigType; - await testClientConfig(clientConfig); - } - ); - return { - type: clientConfigType, - clientConfig, - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if ( - parsedError.errorType === firewallNotConfiguredErrorType || - parsedError.errorType === timeoutErrorType - ) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize( - "mustConfigureFirewall", - "Must configure firewall from Azure Portal to grant access." - ), - code: firewallNotConfiguredErrorType, - }; - } else { - throw error; - } - } - } + try { + await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { + context.errorHandling.rethrow = true; + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.clientConfigType = clientConfigType; + await testClientConfig(clientConfig); + }); + return { + type: clientConfigType, + clientConfig + }; + } catch (error) { + const parsedError = parseError(error); + if (parsedError.errorType === invalidCredentialsErrorType) { + // If the client config failed with invalid credential error, skip and try the next available one. + } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { + // The time out error are common when the firewall rules doesn't grant access from the current IP address. + // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. + throw { + message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), + code: firewallNotConfiguredErrorType + }; + } else { + throw error; + } + } + } - throw { - message: localize( - "mustEnterCredentials", - "Must enter credentials to connect to server." - ), - code: invalidCredentialsErrorType, - }; - } + throw { + message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), + code: invalidCredentialsErrorType + }; + } } diff --git a/Source/postgres/tree/PostgresColumnTreeItem.ts b/Source/postgres/tree/PostgresColumnTreeItem.ts index aedfa46f2..d284c8122 100644 --- a/Source/postgres/tree/PostgresColumnTreeItem.ts +++ b/Source/postgres/tree/PostgresColumnTreeItem.ts @@ -3,30 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; +import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { PostgresTableTreeItem } from './PostgresTableTreeItem'; export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; + public static contextValue: string = "postgresColumn"; + public readonly contextValue: string = PostgresColumnTreeItem.contextValue; + public readonly columnName: string; + public readonly parent: PostgresTableTreeItem; - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } + constructor(parent: PostgresTableTreeItem, columnName: string) { + super(parent); + this.columnName = columnName; + } - public get id(): string { - return this.columnName; - } + public get id(): string { + return this.columnName; + } - public get label(): string { - return this.columnName; - } + public get label(): string { + return this.columnName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('split-horizontal'); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("split-horizontal"); - } } diff --git a/Source/postgres/tree/PostgresDatabaseTreeItem.ts b/Source/postgres/tree/PostgresDatabaseTreeItem.ts index e9463d0bc..05f7a4412 100644 --- a/Source/postgres/tree/PostgresDatabaseTreeItem.ts +++ b/Source/postgres/tree/PostgresDatabaseTreeItem.ts @@ -4,178 +4,112 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line import/no-internal-modules -import { - AzExtParentTreeItem, - AzExtTreeItem, - createContextValue, - GenericTreeItem, - IActionContext, - IParsedError, - parseError, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { - firewallNotConfiguredErrorType, - invalidCredentialsErrorType, -} from "../postgresConstants"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresClientConfigFactory } from "./ClientConfigFactory"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; -import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; -import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; +import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { ThemeIcon } from 'vscode'; +import { ext } from '../../extensionVariables'; +import { localize } from '../../utils/localize'; +import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; +import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; +import { PostgresClientConfigFactory } from './ClientConfigFactory'; +import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; +import { PostgresServerTreeItem } from './PostgresServerTreeItem'; +import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; +import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; + public static contextValue: string = "postgresDatabase"; + public contextValue: string = PostgresDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Resource Type"; + public readonly databaseName: string; + public readonly parent: PostgresServerTreeItem; + public autoSelectInTreeItemPicker: boolean = true; + public isShowingPasswordWarning: boolean; - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } + constructor(parent: PostgresServerTreeItem, databaseName: string) { + super(parent); + this.databaseName = databaseName; + this.isShowingPasswordWarning = false; + } - public get label(): string { - return this.databaseName; - } + public get label(): string { + return this.databaseName; + } - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId - ? localize("connected", "Connected") - : ""; - } + public get description(): string { + return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; + } - public get id(): string { - return this.databaseName; - } + public get id(): string { + return this.databaseName; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("database"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('database'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl( - _clearCache: boolean, - context: IActionContext - ): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: "postgresFirewall", - label: localize( - "configureFirewall", - 'Configure firewall to connect to "{0}"...', - this.parent.label - ), - commandId: "postgreSQL.configureFirewall", - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } + public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { + const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: 'postgresFirewall', + label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), + commandId: 'postgreSQL.configureFirewall' + }); + firewallTreeItem.commandArgs = [this.parent]; + return [firewallTreeItem]; + } - try { - const { type, clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this.parent, - this.databaseName - ); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig), - ]; + try { + const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); + if (type === "password") { + void this.showPasswordWarning(context); + } + const children: AzExtTreeItem[] = [ + new PostgresFunctionsTreeItem(this, clientConfig), + new PostgresTablesTreeItem(this, clientConfig) + ]; - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push( - new PostgresStoredProceduresTreeItem(this, clientConfig) - ); - } + if (await this.parent.supportsStoredProcedures(clientConfig)) { + children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); + } - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); + return children; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if ( - this.parent.azureName && - parsedError.errorType === invalidCredentialsErrorType - ) { - void context.ui.showWarningMessage( - localize( - "couldNotConnect", - 'Could not connect to "{0}": {1}', - this.parent.label, - parsedError.message - ), - { stepName: "loadPostgresDatabases" } - ); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem( - this, - { - contextValue: "postgresCredentials", - label: localize( - "enterCredentials", - 'Enter server credentials to connect to "{0}"...', - this.parent.label - ), - commandId: "postgreSQL.enterCredentials", - } - ); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if ( - this.parent.azureName && - parsedError.errorType === firewallNotConfiguredErrorType - ) { - void context.ui.showWarningMessage( - localize( - "couldNotConnect", - 'Could not connect to "{0}": {1}', - this.parent.label, - parsedError.message - ), - { stepName: "loadPostgresDatabases" } - ); - return []; - } else { - throw error; - } - } - } + if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { + void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); + const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: 'postgresCredentials', + label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), + commandId: 'postgreSQL.enterCredentials' + }); + credentialsTreeItem.commandArgs = [this.parent]; + return [credentialsTreeItem]; + } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { + void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); + return []; + } else { + throw error; + } + } + } - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this.parent, - this.databaseName - ); - await runPostgresQuery( - clientConfig, - `Drop Database ${wrapArgInQuotes(this.databaseName)};` - ); - } + public async deleteTreeItemImpl(): Promise { + const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); + await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); + } - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([ - PostgresDatabaseTreeItem.contextValue, - "usesPassword", - ]); - await this.refresh(context); - } + private async showPasswordWarning(context: IActionContext): Promise { + if (this.isShowingPasswordWarning) { + return; + } + this.isShowingPasswordWarning = true; + this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); + await this.refresh(context); + } } diff --git a/Source/postgres/tree/PostgresFunctionTreeItem.ts b/Source/postgres/tree/PostgresFunctionTreeItem.ts index d7bc46a16..0a26bf3f9 100644 --- a/Source/postgres/tree/PostgresFunctionTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionTreeItem.ts @@ -10,49 +10,39 @@ import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresFunction"; - public readonly contextValue: string = - PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = 'postgresFunction'; + public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; + public readonly parent: PostgresFunctionsTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor( - parent: PostgresFunctionsTreeItem, - row: IPostgresProceduresQueryRow, - isDuplicate: boolean - ) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = "postgreSQL.openFunction"; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = 'postgreSQL.openFunction'; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("symbol-function"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('symbol-function'); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery( - this.parent.clientConfig, - `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${ - this.args - });` - ); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); + } } diff --git a/Source/postgres/tree/PostgresFunctionsTreeItem.ts b/Source/postgres/tree/PostgresFunctionsTreeItem.ts index 8f373ab95..7d3904e83 100644 --- a/Source/postgres/tree/PostgresFunctionsTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionsTreeItem.ts @@ -4,51 +4,43 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from "vscode"; -import { - getPostgresProcedureQueryRows, - IPostgresProceduresQueryRow, -} from "../getPostgresProcedureQueryRows"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { ClientConfig } from 'pg'; +import { ThemeIcon } from 'vscode'; +import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; +import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; +import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresFunctions"; - public readonly contextValue: string = - PostgresFunctionsTreeItem.contextValue; - public readonly label: string = "Functions"; - public readonly childTypeLabel: string = "Function"; - public suppressMaskLabel = true; + public static contextValue: string = 'postgresFunctions'; + public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; + public readonly label: string = 'Functions'; + public readonly childTypeLabel: string = 'Function'; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("symbol-function"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('symbol-function'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = - await getPostgresProcedureQueryRows(this); - return rows.map( - (row) => - new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - ) - ); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); + return rows.map(row => new PostgresFunctionTreeItem( + this, + row, + this.isDuplicateResource(row.name) + )); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresFunctionTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts index 40e4d07c5..b93cc9450 100644 --- a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts +++ b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts @@ -9,19 +9,19 @@ import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; // Base class for Postgres tree items whose children are individual resources export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas + public parent: PostgresDatabaseTreeItem; + public clientConfig: ClientConfig; + public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } + public addResourcesAndSchemasEntry(name: string, schema: string): void { + if (this.resourcesAndSchemas[name]) { + this.resourcesAndSchemas[name].push(schema); + } else { + this.resourcesAndSchemas[name] = [schema]; + } + } - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } + public isDuplicateResource(name: string): boolean { + return this.resourcesAndSchemas[name].length > 1; + } } diff --git a/Source/postgres/tree/PostgresServerTreeItem.ts b/Source/postgres/tree/PostgresServerTreeItem.ts index 1ffc11403..20e7dbe76 100644 --- a/Source/postgres/tree/PostgresServerTreeItem.ts +++ b/Source/postgres/tree/PostgresServerTreeItem.ts @@ -3,383 +3,250 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; -import { - getResourceGroupFromId, - parseAzureResourceId, - uiUtils, -} from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - IActionContext, - ICreateChildImplContext, -} from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { SemVer, coerce, gte } from "semver"; -import * as vscode from "vscode"; -import { - getThemeAgnosticIconPath, - postgresDefaultDatabase, -} from "../../constants"; -import { ext } from "../../extensionVariables"; -import { isIpInRanges } from "../../utils/getIp"; -import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { - AbstractPostgresClient, - createAbstractPostgresClient, -} from "../abstract/AbstractPostgresClient"; -import { PostgresAbstractServer, PostgresServerType } from "../abstract/models"; -import { getPublicIp } from "../commands/configurePostgresFirewall"; -import { ParsedPostgresConnectionString } from "../postgresConnectionStrings"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresClientConfigFactory } from "./ClientConfigFactory"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; -import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; -import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; +import * as SingleModels from '@azure/arm-postgresql'; +import * as FlexibleModels from '@azure/arm-postgresql-flexible'; +import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; +import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; +import { ClientConfig } from 'pg'; +import { SemVer, coerce, gte } from 'semver'; +import * as vscode from 'vscode'; +import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { isIpInRanges } from '../../utils/getIp'; +import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; +import { localize } from '../../utils/localize'; +import { nonNullProp } from '../../utils/nonNull'; +import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; +import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; +import { getPublicIp } from '../commands/configurePostgresFirewall'; +import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; +import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; +import { PostgresClientConfigFactory } from './ClientConfigFactory'; +import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; +import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; +import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; +import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; +import { PostgresTableTreeItem } from './PostgresTableTreeItem'; +import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = - "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor( - parent: AzExtParentTreeItem, - connectionString: ParsedPostgresConnectionString, - server?: PostgresAbstractServer - ) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId) - .provider.toLowerCase() - .includes("flexible") - ? PostgresServerType.Flexible - : PostgresServerType.Single; - } - this.valuesToMask.push( - connectionString.accountId, - connectionString.connectionString, - connectionString.fullId, - connectionString.hostName, - connectionString.port - ); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): - | string - | vscode.Uri - | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath("PostgresServer.svg"); - } - - public get label(): string { - return this.azureName - ? this.azureName - : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean, - context: IActionContext - ): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = - await createAbstractPostgresClient(this.serverType, [ - context, - this.subscription, - ]); - const listOfDatabases: ( - | SingleModels.Database - | FlexibleModels.Database - )[] = await uiUtils.listAllIterator( - client.databases.listByServer( - nonNullProp(this, "resourceGroup"), - nonNullProp(this, "azureName") - ) - ); - dbNames = listOfDatabases.map((db) => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this, - postgresDefaultDatabase - ); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map((db) => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - "invalidPostgresServer", - (dbName) => - dbName && !["azure_maintenance", "azure_sys"].includes(dbName) - ? new PostgresDatabaseTreeItem(this, dbName) - : undefined, - (dbName) => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl( - context: ICreateChildImplContext - ): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error( - localize( - "noPermissionToCreateDatabase", - `This attached account does not have permissions to create a database.` - ) - ); - } - const getChildrenTask: Promise = - this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: "createPostgresDatabase", - validateInput: (name: string) => - validateDatabaseName(name, getChildrenTask), - }); - const { clientConfig } = - await PostgresClientConfigFactory.getClientConfigFromNode( - this, - databaseName - ); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery( - clientConfig, - `Create Database ${wrapArgInQuotes(databaseName)};` - ); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [ - context, - this.subscription, - ]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: deletingMessage, - }, - async () => { - await client.servers.beginDeleteAndWait( - nonNullProp(this, "resourceGroup"), - nonNullProp(this, "azureName") - ); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize( - "deleteServerMsg", - 'Successfully deleted server "{0}".', - this.label - ); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - } - ); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures( - clientConfig: ClientConfig - ): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery( - clientConfig, - `SHOW server_version;` - ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, "11.0.0"); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = - ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue - ? JSON.parse(storedValue) - : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { - return server.id !== this.id; - }); - - await ext.context.globalState.update( - serviceName, - JSON.stringify(servers) - ); - await ext.secretStorage.delete( - getSecretStorageKey(serviceName, this.id) - ); - } - - public async getFullConnectionString(): Promise { - if ( - this.azureId && - !( - this.partialConnectionString.username && - this.partialConnectionString.password - ) - ) { - const storedValue: string | undefined = ext.context.globalState.get( - PostgresServerTreeItem.serviceName - ); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = - (await ext.secretStorage.get( - getSecretStorageKey( - PostgresServerTreeItem.serviceName, - this.id - ) - )) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp( - this, - "serverType" - ); - const client: AbstractPostgresClient = - await createAbstractPostgresClient(serverType, [ - context, - this.subscription, - ]); - const results: SingleModels.FirewallRule[] = - await uiUtils.listAllIterator( - client.firewallRules.listByServer( - nonNullProp(this, "resourceGroup"), - nonNullProp(this, "azureName") - ) - ); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } + public static contextValue: string = "postgresServer"; + public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; + public readonly contextValue: string = PostgresServerTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly serverType: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { + super(parent); + this.partialConnectionString = connectionString; + if (server) { + this.azureId = server?.id; + this.serverVersion = server?.version; + this.resourceGroup = getResourceGroupFromId(this.fullId); + this.azureName = server?.name; + this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; + } + this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); + if (connectionString.databaseName) { + this.valuesToMask.push(connectionString.databaseName); + } + } + + public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath('PostgresServer.svg'); + } + + public get label(): string { + return this.azureName ? this.azureName : this.partialConnectionString.fullId; + } + + public get id(): string { + if (this.azureId) { + return this.azureId; + } + return this.partialConnectionString.fullId; + } + + public get description(): string | undefined { + switch (this.serverType) { + case PostgresServerType.Flexible: + return "PostgreSQL Flexible"; + case PostgresServerType.Single: + return "PostgreSQL Single"; + default: + return "PostgreSQL"; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { + context.telemetry.properties.serverType = this.serverType; + let dbNames: (string | undefined)[]; + if (this.azureName) { + const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); + const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); + dbNames = listOfDatabases.map(db => db.name); + } else if (this.partialConnectionString.databaseName) { + dbNames = [this.partialConnectionString.databaseName]; + } else { + const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); + const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; + const queryResult = await runPostgresQuery(clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + dbNames = queryResult.rows.map(db => db?.datname); + } + + return this.createTreeItemsWithErrorHandling( + dbNames, + 'invalidPostgresServer', + dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, + dbName => dbName + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case PostgresDatabaseTreeItem.contextValue: + case PostgresTablesTreeItem.contextValue: + case PostgresTableTreeItem.contextValue: + case PostgresFunctionsTreeItem.contextValue: + case PostgresFunctionTreeItem.contextValue: + case PostgresStoredProceduresTreeItem.contextValue: + case PostgresStoredProcedureTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async createChildImpl(context: ICreateChildImplContext): Promise { + if (this.partialConnectionString.databaseName) { + throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); + } + const getChildrenTask: Promise = this.getCachedChildren(context); + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: 'createPostgresDatabase', + validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) + }); + const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); + context.showCreatingTreeItem(databaseName); + await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); + return new PostgresDatabaseTreeItem(this, databaseName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); + const deletingMessage: string = `Deleting server "${this.label}"...`; + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { + await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); + await this.deletePostgresCredentials(); + + const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + }); + } + + public setCredentials(username: string, password: string): void { + this.partialConnectionString.username = username; + this.partialConnectionString.password = password; + } + + public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { + // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer + if (!this.serverVersion) { + const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + this.serverVersion = result.rows[0].server_version; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + const version: SemVer | null = coerce(this.serverVersion); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call + return gte(version, '11.0.0'); + } + + public async deletePostgresCredentials(): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; + + // Remove this server from the cache + servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); + + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); + } + + public async getFullConnectionString(): Promise { + + if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { + const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); + if (storedValue) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const servers: IPersistedServer[] = JSON.parse(storedValue); + for (const server of servers) { + if (server.id === this.id) { + this.partialConnectionString.username = server.username; + // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials + this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; + break; + } + } + } + } + return this.partialConnectionString; + } + + /** + * @returns true if we believe the firewall allows the current IP to connect to database server. + */ + public async isFirewallRuleSet(context: IActionContext): Promise { + try { + const serverType: PostgresServerType = nonNullProp(this, 'serverType'); + const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); + const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); + const publicIp: string = await getPublicIp(context); + return isIpInRanges(publicIp, results); + } catch (error) { + // We cannot get the firewall rules from attached databases because we cannot get the subscription object. + // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. + return true; + } + } } -async function validateDatabaseName( - name: string, - getChildrenTask: Promise -): Promise { - if (!name) { - return localize("NameCannotBeEmpty", "Name cannot be empty."); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize("NameExists", 'Database "{0}" already exists.', name); - } - return undefined; +async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { + if (!name) { + return localize('NameCannotBeEmpty', 'Name cannot be empty.'); + } + const currDatabaseList = await getChildrenTask; + const currDatabaseNames: string[] = []; + for (const db of currDatabaseList) { + if (db instanceof PostgresDatabaseTreeItem) { + currDatabaseNames.push(db.databaseName); + } + } + if (currDatabaseNames.includes(name)) { + return localize('NameExists', 'Database "{0}" already exists.', name); + } + return undefined; } diff --git a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts index 1c903d9e2..503d0ae74 100644 --- a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts @@ -10,47 +10,39 @@ import { runPostgresQuery } from "../runPostgresQuery"; import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresStoredProcedure"; - public readonly contextValue: string = - PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = 'postgresStoredProcedure'; + public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; + public readonly parent: PostgresStoredProceduresTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor( - parent: PostgresStoredProceduresTreeItem, - row: IPostgresProceduresQueryRow, - isDuplicate: boolean - ) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = "postgreSQL.openStoredProcedure"; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = 'postgreSQL.openStoredProcedure'; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("server-process"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('server-process'); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery( - this.parent.clientConfig, - `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});` - ); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); + } } diff --git a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts index 9525856f6..1c516e00f 100644 --- a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts @@ -4,53 +4,43 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from "vscode"; -import { - getPostgresProcedureQueryRows, - IPostgresProceduresQueryRow, -} from "../getPostgresProcedureQueryRows"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; -import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; +import { ClientConfig } from 'pg'; +import { ThemeIcon } from 'vscode'; +import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; +import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; +import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresStoredProcedures"; - public readonly contextValue: string = - PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = "Stored Procedures"; - public readonly childTypeLabel: string = "Stored Procedure"; - public suppressMaskLabel = true; + public static contextValue: string = 'postgresStoredProcedures'; + public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; + public readonly label: string = 'Stored Procedures'; + public readonly childTypeLabel: string = 'Stored Procedure'; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("server-process"); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('server-process'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise< - PostgresStoredProcedureTreeItem[] - > { - const rows: IPostgresProceduresQueryRow[] = - await getPostgresProcedureQueryRows(this); - return rows.map( - (row) => - new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - ) - ); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); + return rows.map(row => new PostgresStoredProcedureTreeItem( + this, + row, + this.isDuplicateResource(row.name) + )); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresStoredProcedureTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresTableTreeItem.ts b/Source/postgres/tree/PostgresTableTreeItem.ts index fb844038b..ef5d87c2c 100644 --- a/Source/postgres/tree/PostgresTableTreeItem.ts +++ b/Source/postgres/tree/PostgresTableTreeItem.ts @@ -3,68 +3,54 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtParentTreeItem, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { IPostgresTable } from "../getTables"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresColumnTreeItem } from "./PostgresColumnTreeItem"; -import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; +import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { IPostgresTable } from '../getTables'; +import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; +import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; +import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; + public static contextValue: string = "postgresTable"; + public readonly contextValue: string = PostgresTableTreeItem.contextValue; + public readonly table: IPostgresTable; + public readonly parent: PostgresTablesTreeItem; - private _isDuplicate: boolean; + private _isDuplicate: boolean; - constructor( - parent: PostgresTablesTreeItem, - table: IPostgresTable, - isDuplicate: boolean - ) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } + constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { + super(parent); + this.table = table; + this._isDuplicate = isDuplicate; + } - public get id(): string { - return String(this.table.oid); - } + public get id(): string { + return String(this.table.oid); + } - public get label(): string { - return this.table.name; - } + public get label(): string { + return this.table.name; + } - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } + public get description(): string | undefined { + return this._isDuplicate ? this.table.schemaName : undefined; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("window"); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('window'); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - return this.table.columnNames.map( - (columnName) => new PostgresColumnTreeItem(this, columnName) - ); - } + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + + return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); + } + + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery( - this.parent.clientConfig, - `Drop Table ${this.table.schemaName}.${wrapArgInQuotes( - this.table.name - )};` - ); - } } diff --git a/Source/postgres/tree/PostgresTablesTreeItem.ts b/Source/postgres/tree/PostgresTablesTreeItem.ts index 4c15ef812..c18c065db 100644 --- a/Source/postgres/tree/PostgresTablesTreeItem.ts +++ b/Source/postgres/tree/PostgresTablesTreeItem.ts @@ -5,54 +5,47 @@ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { ThemeIcon } from "vscode"; +import { ThemeIcon } from 'vscode'; import { getTables, IPostgresTable } from "../getTables"; import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = "Tables"; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon("window"); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry( - table.name.trim(), - table.schemaName - ); - } - return tables.map( - (table) => - new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - ) - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } + public static contextValue: string = "postgresTables"; + public readonly contextValue: string = PostgresTablesTreeItem.contextValue; + public readonly childTypeLabel: string = "Table"; + public readonly label: string = 'Tables'; + public suppressMaskLabel = true; + + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } + + public get iconPath(): TreeItemIconPath { + return new ThemeIcon('window'); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + + const tables: IPostgresTable[] = await getTables(this.clientConfig); + this.resourcesAndSchemas = {}; + for (const table of tables) { + this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); + } + return tables.map(table => new PostgresTableTreeItem( + this, + table, + this.isDuplicateResource(table.name.trim()) + )); + } + + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresTableTreeItem.contextValue; + } } diff --git a/Source/resolver/AppResolver.ts b/Source/resolver/AppResolver.ts index 7d20a4832..0f75cdf29 100644 --- a/Source/resolver/AppResolver.ts +++ b/Source/resolver/AppResolver.ts @@ -4,19 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, - ISubscriptionContext, - nonNullProp, - nonNullValue, -} from "@microsoft/vscode-azext-utils"; -import { - AppResource, - AppResourceResolver, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; +import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; import { tryGetExperience } from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; import { ext } from "../extensionVariables"; @@ -24,111 +13,59 @@ import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresAbstractServer } from "../postgres/abstract/models"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { - createCosmosDBClient, - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../utils/azureClients"; +import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; const resourceTypes = [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers", + 'microsoft.documentdb/databaseaccounts', + 'microsoft.dbforpostgresql/servers', + 'microsoft.dbforpostgresql/flexibleservers' ]; export class DatabaseResolver implements AppResourceResolver { - public async resolveResource( - subContext: ISubscriptionContext, - resource: AppResource - ): Promise { - return await callWithTelemetryAndErrorHandling( - "resolveResource", - async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = - await ext.rgApi.appResourceTree.findTreeItem( - `/subscriptions/${subContext.subscriptionId}`, - context - ); - try { - const resourceGroupName = getResourceGroupFromId( - nonNullProp(resource, "id") - ); - const name = nonNullProp(resource, "name"); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; + public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { + return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { + const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); + try { + const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); + const name = nonNullProp(resource, 'name'); + let postgresServer: PostgresAbstractServer; + let dbChild: AzExtTreeItem; - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ - ...context, - ...subContext, - }); - const databaseAccount = - await client.databaseAccounts.get( - resourceGroupName, - name - ); - dbChild = - await SubscriptionTreeItem.initCosmosDBChild( - client, - databaseAccount, - nonNullValue(subNode) - ); - const experience = - tryGetExperience(databaseAccount); + switch (resource.type.toLowerCase()) { + case resourceTypes[0]: + const client = await createCosmosDBClient({ ...context, ...subContext }); + const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); + dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); + const experience = tryGetExperience(databaseAccount); - return experience?.api === "MongoDB" - ? new ResolvedMongoAccountResource( - dbChild as MongoAccountTreeItem, - resource - ) - : new ResolvedDocDBAccountResource( - dbChild as DocDBAccountTreeItem, - resource - ); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = - resource.type.toLowerCase() === resourceTypes[1] - ? await createPostgreSQLClient({ - ...context, - ...subContext, - }) - : await createPostgreSQLFlexibleClient({ - ...context, - ...subContext, - }); + return experience?.api === 'MongoDB' ? + new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : + new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); + case resourceTypes[1]: + case resourceTypes[2]: + const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? + await createPostgreSQLClient({ ...context, ...subContext }) : + await createPostgreSQLFlexibleClient({ ...context, ...subContext }); - postgresServer = await postgresClient.servers.get( - resourceGroupName, - name - ); - dbChild = - await SubscriptionTreeItem.initPostgresChild( - postgresServer, - nonNullValue(subNode) - ); + postgresServer = await postgresClient.servers.get(resourceGroupName, name); + dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); - return new ResolvedPostgresServerResource( - dbChild as PostgresServerTreeItem, - resource - ); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - } - ); - } + return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); + default: + return null; + } + } catch (e) { + console.error({ ...context, ...subContext }); + throw e; + } + }); + } - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } + public matchesResource(resource: AppResource): boolean { + return resourceTypes.includes(resource.type.toLowerCase()); + } } diff --git a/Source/resolver/DatabaseWorkspaceProvider.ts b/Source/resolver/DatabaseWorkspaceProvider.ts index d1f462a36..14e50d643 100644 --- a/Source/resolver/DatabaseWorkspaceProvider.ts +++ b/Source/resolver/DatabaseWorkspaceProvider.ts @@ -3,37 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtParentTreeItem, - AzExtTreeItem, - callWithTelemetryAndErrorHandling, - IActionContext, -} from "@microsoft/vscode-azext-utils"; +import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; import { Disposable } from "vscode"; import { ext } from "../extensionVariables"; import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; + export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise< - AzExtTreeItem[] | null | undefined - > { - return await callWithTelemetryAndErrorHandling( - "AzureAccountTreeItemWithProjects.provideResources", - async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - } - ); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } + + public disposables: Disposable[] = []; + + constructor(parent: AzExtParentTreeItem) { + ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); + } + + public async provideResources(): Promise { + + return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { + return [ext.attachedAccountsNode]; + }); + } + private _projectDisposables: Disposable[] = []; + + public dispose(): void { + Disposable.from(...this._projectDisposables).dispose(); + } } + diff --git a/Source/resolver/ResolvedDatabaseAccountResource.ts b/Source/resolver/ResolvedDatabaseAccountResource.ts index 41eda32be..0222dded7 100644 --- a/Source/resolver/ResolvedDatabaseAccountResource.ts +++ b/Source/resolver/ResolvedDatabaseAccountResource.ts @@ -3,78 +3,55 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzExtTreeItem, - IActionContext, - ICreateChildImplContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -export class ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?( - clearCache: boolean, - context: IActionContext - ): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?( - expectedContextValues: (string | RegExp)[], - context: IActionContext - ): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor( - ti: - | DocDBAccountTreeItemBase - | MongoAccountTreeItem - | PostgresServerTreeItem, - resource: AppResource - ) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = - ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue); - this.maskedValuestoAdd.push(...ti.valuesToMask); - } +export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + public id: string; + public contextValuesToAdd: string[] = []; + public description: string | undefined; + + // private _databaseTreeItem: AzExtParentTreeItem; + iconPath: TreeItemIconPath | undefined; + label: string; + + readonly childTypeLabel: string; + + loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; + createChildImpl?(context: ICreateChildImplContext): Promise; + hasMoreChildrenImpl?(): boolean; + compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; + + pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; + deleteTreeItemImpl?(context: IActionContext): Promise; + refreshImpl?(context: IActionContext): Promise; + isAncestorOfImpl?(contextValue: string): boolean; + + connectionString: string; + maskedValuestoAdd: string[] = []; + + public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { + this.id = ti.id ?? resource.id; + // PostgresServerTreeItem require on a property on the server so wait to do this + this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; + this.iconPath = ti.iconPath; + this.label = ti.label; + this.childTypeLabel = ti.childTypeLabel; + + this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; + this.createChildImpl = ti.createChildImpl; + this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; + this.compareChildrenImpl = ti.compareChildrenImpl; + + this.pickTreeItemImpl = ti.pickTreeItemImpl; + this.deleteTreeItemImpl = ti.deleteTreeItemImpl; + this.refreshImpl = ti.refreshImpl; + this.isAncestorOfImpl = ti.isAncestorOfImpl; + + this.contextValuesToAdd.push(ti.contextValue) + this.maskedValuestoAdd.push(...ti.valuesToMask); + } } diff --git a/Source/resolver/ResolvedDocDBAccountResource.ts b/Source/resolver/ResolvedDocDBAccountResource.ts index 02f17f6e3..cf1bfc4bc 100644 --- a/Source/resolver/ResolvedDocDBAccountResource.ts +++ b/Source/resolver/ResolvedDocDBAccountResource.ts @@ -1,45 +1,32 @@ + + /*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { - CosmosClient, - DatabaseDefinition, - FeedOptions, - QueryIterator, - Resource, -} from "@azure/cosmos"; +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ + +import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedDocDBAccountResource - extends ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: ( - client: CosmosClient, - feedOptions: FeedOptions - ) => QueryIterator; - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless; - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } +export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + public root: IDocDBTreeRoot; + + initChild: (resource: Resource) => AzExtTreeItem; + isServerless?: boolean; + getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator + + public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { + super(ti, resource); + + this.connectionString = ti.connectionString; + this.root = ti.root; + + this.isServerless = ti.isServerless + this.getIterator = ti.getIterator; + this.initChild = ti.initChild; + } } diff --git a/Source/resolver/ResolvedMongoAccountResource.ts b/Source/resolver/ResolvedMongoAccountResource.ts index 80636b5e5..4f45486ef 100644 --- a/Source/resolver/ResolvedMongoAccountResource.ts +++ b/Source/resolver/ResolvedMongoAccountResource.ts @@ -3,24 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedMongoAccountResource - extends ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - root: IMongoTreeRoot; +export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + root: IMongoTreeRoot; - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); + public constructor(ti: MongoAccountTreeItem, resource: AppResource) { + super(ti, resource); - this.connectionString = ti.connectionString; - this.root = ti.root; - } + this.connectionString = ti.connectionString; + this.root = ti.root; + } } diff --git a/Source/resolver/ResolvedPostgresServerResource.ts b/Source/resolver/ResolvedPostgresServerResource.ts index 76007eac0..a1e35acf3 100644 --- a/Source/resolver/ResolvedPostgresServerResource.ts +++ b/Source/resolver/ResolvedPostgresServerResource.ts @@ -4,54 +4,45 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { - AppResource, - ResolvedAppResourceBase, -} from "@microsoft/vscode-azext-utils/hostapi"; +import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; import { ClientConfig } from "pg"; import { PostgresServerType } from "../postgres/abstract/models"; import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedPostgresServerResource - extends ResolvedDatabaseAccountResource - implements ResolvedAppResourceBase -{ - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise; - deletePostgresCredentials: () => Promise; - getFullConnectionString: () => Promise; - validateDatabaseName: ( - name: string, - getChildrenTask: Promise - ) => Promise; - isFirewallRuleSet: (context: IActionContext) => Promise; - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } +export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { + public readonly serverType?: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + setCredentials: (username: string, password: string) => void; + supportsStoredProcedures: (clientConfig: ClientConfig) => Promise + deletePostgresCredentials: () => Promise + getFullConnectionString: () => Promise + validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise + isFirewallRuleSet: (context: IActionContext) => Promise + + public constructor(ti: PostgresServerTreeItem, resource: AppResource) { + super(ti, resource); + this.serverType = ti.serverType; + this.description = ti.description; + this.resourceGroup = ti.resourceGroup; + this.azureName = ti.azureName; + this.partialConnectionString = ti.partialConnectionString; + + this.azureId = ti.azureId; + this.serverVersion = ti.serverVersion; + + this.setCredentials = ti.setCredentials; + this.supportsStoredProcedures = ti.supportsStoredProcedures; + this.deletePostgresCredentials = ti.deletePostgresCredentials; + this.getFullConnectionString = ti.getFullConnectionString; + this.isFirewallRuleSet = ti.isFirewallRuleSet; + } } diff --git a/Source/table/tree/TableAccountTreeItem.ts b/Source/table/tree/TableAccountTreeItem.ts index fb2616da9..0d3b86e38 100644 --- a/Source/table/tree/TableAccountTreeItem.ts +++ b/Source/table/tree/TableAccountTreeItem.ts @@ -4,40 +4,36 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBTableAccount"; + public contextValue: string = TableAccountTreeItem.contextValue; - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public initChild(): AzExtTreeItem { - throw new Error("Table Accounts are not supported yet."); - } + public initChild(): AzExtTreeItem { + throw new Error('Table Accounts are not supported yet.'); + } - public async loadMoreChildrenImpl( - _clearCache: boolean - ): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: "tableNotSupported", - label: "Table Accounts are not supported yet.", - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } + public async loadMoreChildrenImpl(_clearCache: boolean): Promise { + const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: 'tableNotSupported', + label: 'Table Accounts are not supported yet.' + }); + tableNotFoundTreeItem.suppressMaskLabel = true; + return [tableNotFoundTreeItem]; + } - public async deleteTreeItemImpl( - context: IDeleteWizardContext - ): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { + await deleteCosmosDBAccount(context, this); + } - public isAncestorOfImpl(): boolean { - return false; - } + public isAncestorOfImpl(): boolean { + return false; + } } diff --git a/Source/tree/AttachedAccountsTreeItem.ts b/Source/tree/AttachedAccountsTreeItem.ts index 47aa8bdc3..d854e506f 100644 --- a/Source/tree/AttachedAccountsTreeItem.ts +++ b/Source/tree/AttachedAccountsTreeItem.ts @@ -3,605 +3,418 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - appendExtensionUserAgent, - AzExtParentTreeItem, - AzExtTreeItem, - GenericTreeItem, - IActionContext, - ISubscriptionContext, - TreeItemIconPath, -} from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import * as vscode from "vscode"; -import { - API, - getExperienceFromApi, - getExperienceQuickPick, - getExperienceQuickPicks, -} from "../AzureDBExperiences"; -import { removeTreeItemFromCache } from "../commands/api/apiCache"; -import { emulatorPassword, isWindows } from "../constants"; -import { parseDocDBConnectionString } from "../docdb/docDBConnectionStrings"; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { ext } from "../extensionVariables"; -import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { connectToMongoClient } from "../mongo/connectToMongoClient"; -import { parseMongoConnectionString } from "../mongo/mongoConnectionStrings"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { parsePostgresConnectionString } from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { getSecretStorageKey } from "../utils/getSecretStorageKey"; -import { localize } from "../utils/localize"; -import { nonNullProp, nonNullValue } from "../utils/nonNull"; -import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; +import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { MongoClient } from 'mongodb'; +import * as vscode from 'vscode'; +import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; +import { removeTreeItemFromCache } from '../commands/api/apiCache'; +import { emulatorPassword, isWindows } from '../constants'; +import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; +import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; +import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; +import { ext } from '../extensionVariables'; +import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; +import { connectToMongoClient } from '../mongo/connectToMongoClient'; +import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; +import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; +import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; +import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; +import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; +import { getSecretStorageKey } from '../utils/getSecretStorageKey'; +import { localize } from '../utils/localize'; +import { nonNullProp, nonNullValue } from '../utils/nonNull'; +import { SubscriptionTreeItem } from './SubscriptionTreeItem'; interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; + id: string; + // defaultExperience is not the same as API but we can't change the name due to backwards compatibility + defaultExperience: API; + isEmulator: boolean | undefined; } -export const AttachedAccountSuffix: string = "Attached"; -export const MONGO_CONNECTION_EXPECTED: string = - 'Connection string must start with "mongodb://" or "mongodb+srv://"'; +export const AttachedAccountSuffix: string = 'Attached'; +export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; -const localMongoConnectionString: string = "mongodb://127.0.0.1:27017"; +const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = - "cosmosDBAttachedAccounts" + - (isWindows ? "WithEmulator" : "WithoutEmulator"); - public readonly contextValue: string = - AttachedAccountsTreeItem.contextValue; - public readonly label: string = "Attached Database Accounts"; - public childTypeLabel: string = "Account"; - public suppressMaskLabel = true; - - private readonly _serviceName: string = - "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = "cosmosDBAttachedAccounts"; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon("plug"); - } - - public static validateMongoConnectionString( - value: string - ): string | undefined { - value = value ? value.trim() : ""; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString( - value: string - ): string | undefined { - value = value ? value.trim() : ""; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize( - "invalidPostgresConnectionString", - 'Connection string must start with "postgres://"' - ); - } - - private static validateDocDBConnectionString( - value: string - ): string | undefined { - value = value ? value.trim() : ""; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - clearCache: boolean - ): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = - await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: "cosmosDBAttachDatabaseAccount", - label: "Attach Database Account...", - commandId: "cosmosDB.attachDatabaseAccount", - includeInTreeItemPicker: true, - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: "cosmosDBAttachEmulator", - label: "Attach Emulator...", - commandId: "cosmosDB.attachEmulator", - includeInTreeItemPicker: true, - }); - return isWindows - ? [attachDatabaseAccount, attachEmulator] - : [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick( - getExperienceQuickPicks(true), - { - placeHolder: "Select a Database type...", - stepName: "attachNewAccount", - } - ); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = "mongodb://host:port"; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = - AttachedAccountsTreeItem.validateMongoConnectionString; - } else if ( - defaultExperience.api === API.PostgresSingle || - defaultExperience.api === API.PostgresFlexible - ) { - placeholder = localize( - "attachedPostgresPlaceholder", - '"postgres://username:password@host" or "postgres://username:password@host/database"' - ); - validateInput = - AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = "AccountEndpoint=...;AccountKey=..."; - validateInput = - AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = ( - await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: "Enter the connection string for your database account", - stepName: "attachNewAccountConnectionString", - validateInput: validateInput, - value: defaultValue, - }) - ).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem( - connectionString, - defaultExperience.api - ); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString( - context: IActionContext, - connectionString: string, - api: API.MongoDB | API.Core | API.PostgresSingle - ): Promise< - MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem - > { - const treeItem = < - | MongoAccountTreeItem - | DocDBAccountTreeItemBase - | PostgresServerTreeItem - >await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core), - ], - { - placeHolder: "Select a Database Account API...", - stepName: "attachEmulator", - } - ); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace - .getConfiguration() - .get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace - .getConfiguration() - .get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent( - emulatorPassword - )}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem( - connectionString, - defaultExperience.api, - label - ); - if ( - treeItem instanceof DocDBAccountTreeItem || - treeItem instanceof GraphAccountTreeItem || - treeItem instanceof TableAccountTreeItem || - treeItem instanceof MongoAccountTreeItem - ) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = - await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex( - (account) => account.fullId === node.fullId - ); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete( - getSecretStorageKey(this._serviceName, nonNullProp(node, "id")) - ); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString( - node.connectionString - ); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString( - node.connectionString - ); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error( - "Failed to load persisted Database Accounts. Reattach the accounts manually." - ); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient( - localMongoConnectionString, - appendExtensionUserAgent() - ); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount( - context: IActionContext, - treeItem: AzExtTreeItem, - connectionString: string - ): Promise { - const attachedAccounts: AzExtTreeItem[] = - await this.getAttachedAccounts(); - - if (attachedAccounts.find((s) => s.id === treeItem.id)) { - void context.ui.showWarningMessage( - `Database Account '${treeItem.id}' is already attached.`, - { stepName: "attachAccount" } - ); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store( - getSecretStorageKey( - this._serviceName, - nonNullProp(treeItem, "id") - ), - connectionString - ); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get( - this._serviceName - ); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all( - accounts.map(async (account) => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof account === "string") { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${ - getExperienceFromApi(api).shortName - })`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator - ? `${getExperienceFromApi(api).shortName} Emulator` - : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue( - await ext.secretStorage.get( - getSecretStorageKey(this._serviceName, id) - ), - "connectionString" - ); - persistedAccounts.push( - await this.createTreeItem( - connectionString, - api, - label, - id, - isEmulator - ) - ); - }) - ); - } - - return persistedAccounts; - } - - private async createTreeItem( - connectionString: string, - api: API, - label?: string, - id?: string, - isEmulator?: boolean - ): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = - await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem( - this, - id, - label, - connectionString, - isEmulator - ); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = - parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem( - this, - parsedPostgresConnString - ); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = - label || - `${parsedCS.accountId} (${ - getExperienceFromApi(api).shortName - })`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem( - this, - parsedCS.accountId, - label, - parsedCS.documentEndpoint, - parsedCS.masterKey, - isEmulator - ); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem( - this, - parsedCS.accountId, - label, - parsedCS.documentEndpoint, - undefined, - parsedCS.masterKey, - isEmulator - ); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem( - this, - parsedCS.accountId, - label, - parsedCS.documentEndpoint, - parsedCS.masterKey, - isEmulator - ); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map( - (node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if ( - node instanceof MongoAccountTreeItem || - node instanceof DocDBAccountTreeItem || - node instanceof GraphAccountTreeItem || - node instanceof TableAccountTreeItem - ) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error( - `Unexpected account node "${node.constructor.name}".` - ); - } - return { - id: nonNullProp(node, "id"), - defaultExperience: api, - isEmulator: isEmulator, - }; - } - ); - await ext.context.globalState.update( - this._serviceName, - JSON.stringify(value) - ); - } + public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); + public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; + public readonly label: string = 'Attached Database Accounts'; + public childTypeLabel: string = 'Account'; + public suppressMaskLabel = true; + + private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; + private _attachedAccounts: AzExtTreeItem[] | undefined; + + private _root: ISubscriptionContext; + private _loadPersistedAccountsTask: Promise; + + constructor(parent: AzExtParentTreeItem) { + super(parent); + this._root = new AttachedAccountRoot(); + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + this.id = 'cosmosDBAttachedAccounts'; + } + + public get root(): ISubscriptionContext { + return this._root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon('plug'); + } + + public static validateMongoConnectionString(value: string): string | undefined { + value = value ? value.trim() : ''; + + if (value && value.match(/^mongodb(\+srv)?:\/\//)) { + return undefined; + } + + return MONGO_CONNECTION_EXPECTED; + } + + public static validatePostgresConnectionString(value: string): string | undefined { + value = value ? value.trim() : ''; + + if (value && value.match(/^postgres:\/\//)) { + return undefined; + } + + return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); + } + + private static validateDocDBConnectionString(value: string): string | undefined { + value = value ? value.trim() : ''; + + try { + parseDocDBConnectionString(value); + return undefined; + } catch (error) { + return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(clearCache: boolean): Promise { + if (clearCache) { + this._attachedAccounts = undefined; + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + } + + const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); + + if (attachedAccounts.length > 0) { + return attachedAccounts; + } else { + const attachDatabaseAccount = new GenericTreeItem(this, { + contextValue: 'cosmosDBAttachDatabaseAccount', + label: 'Attach Database Account...', + commandId: 'cosmosDB.attachDatabaseAccount', + includeInTreeItemPicker: true + }); + const attachEmulator = new GenericTreeItem(this, { + contextValue: 'cosmosDBAttachEmulator', + label: 'Attach Emulator...', + commandId: 'cosmosDB.attachEmulator', + includeInTreeItemPicker: true + }); + return isWindows ? [attachDatabaseAccount, attachEmulator] : + [attachDatabaseAccount]; + } + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + // We have to make sure the Attached Accounts node is not shown for commands like + // 'Open in Portal', which only work for the non-attached version + case GraphAccountTreeItem.contextValue: + case MongoAccountTreeItem.contextValue: + case DocDBAccountTreeItem.contextValue: + case TableAccountTreeItem.contextValue: + case PostgresServerTreeItem.contextValue: + case SubscriptionTreeItem.contextValue: + return false; + default: + return true; + } + } + + public async attachNewAccount(context: IActionContext): Promise { + const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); + const defaultExperience = defaultExperiencePick.data; + let placeholder: string; + let defaultValue: string | undefined; + let validateInput: (value: string) => string | undefined | null; + if (defaultExperience.api === API.MongoDB) { + placeholder = 'mongodb://host:port'; + if (await this.canConnectToLocalMongoDB()) { + defaultValue = placeholder = localMongoConnectionString; + } + validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; + } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { + placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); + validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; + } else { + placeholder = 'AccountEndpoint=...;AccountKey=...'; + validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; + } + + const connectionString = (await context.ui.showInputBox({ + placeHolder: placeholder, + prompt: 'Enter the connection string for your database account', + stepName: 'attachNewAccountConnectionString', + validateInput: validateInput, + value: defaultValue + })).trim(); + + const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); + await this.attachAccount(context, treeItem, connectionString); + } + + public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { + const treeItem = await this.createTreeItem(connectionString, api); + await this.attachAccount(context, treeItem, connectionString); + await this.refresh(context); + return treeItem; + } + + public async attachEmulator(context: IActionContext): Promise { + let connectionString: string; + const defaultExperiencePick = await context.ui.showQuickPick( + [ + getExperienceQuickPick(API.MongoDB), + getExperienceQuickPick(API.Core) + ], + { + placeHolder: "Select a Database Account API...", + stepName: 'attachEmulator' + }); + const defaultExperience = defaultExperiencePick.data; + let port: number | undefined; + if (defaultExperience.api === API.MongoDB) { + port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); + } else { + port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); + } + if (port) { + if (defaultExperience.api === API.MongoDB) { + // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions + connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; + } else { + connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; + } + const label = `${defaultExperience.shortName} Emulator`; + const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); + if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { + // CONSIDER: Why isn't this passed in to createTreeItem above? + treeItem.root.isEmulator = true; + } + await this.attachAccount(context, treeItem, connectionString); + } + } + + public async detach(node: AzExtTreeItem): Promise { + const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); + + const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); + if (index !== -1) { + attachedAccounts.splice(index, 1); + await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility + await this.persistIds(attachedAccounts); + + if (node instanceof MongoAccountTreeItem) { + const parsedCS = await parseMongoConnectionString(node.connectionString); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof DocDBAccountTreeItemBase) { + const parsedCS = parseDocDBConnectionString(node.connectionString); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof PostgresServerTreeItem) { + const parsedCS = node.partialConnectionString; + removeTreeItemFromCache(parsedCS); + } + } + } + + private async getAttachedAccounts(): Promise { + if (!this._attachedAccounts) { + try { + this._attachedAccounts = await this._loadPersistedAccountsTask; + } catch { + this._attachedAccounts = []; + throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); + } + } + + return this._attachedAccounts; + } + + private async canConnectToLocalMongoDB(): Promise { + async function timeout(): Promise { + await delay(1000); + return false; + } + async function connect(): Promise { + try { + const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); + void db.close(); + return true; + } catch { + return false; + } + } + return await Promise.race([timeout(), connect()]); + } + + private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { + const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); + + if (attachedAccounts.find(s => s.id === treeItem.id)) { + void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); + } else { + attachedAccounts.push(treeItem); + await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); + await this.persistIds(attachedAccounts); + } + } + + private async loadPersistedAccounts(): Promise { + const persistedAccounts: AzExtTreeItem[] = []; + const value: string | undefined = ext.context.globalState.get(this._serviceName); + if (value) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const accounts: (string | IPersistedAccount)[] = JSON.parse(value); + await Promise.all(accounts.map(async account => { + let id: string; + let label: string; + let api: API; + let isEmulator: boolean | undefined; + if (typeof (account) === 'string') { + // Default to Mongo if the value is a string for the sake of backwards compatibility + // (Mongo was originally the only account type that could be attached) + id = account; + api = API.MongoDB; + label = `${account} (${getExperienceFromApi(api).shortName})`; + isEmulator = false; + } else { + id = (account).id; + api = (account).defaultExperience; + isEmulator = (account).isEmulator; + label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; + } + // TODO: keytar: migration plan? + const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); + persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); + })); + } + + return persistedAccounts; + } + + private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { + let treeItem: AzExtTreeItem; + if (api === API.MongoDB) { + if (id === undefined) { + const parsedCS = await parseMongoConnectionString(connectionString); + id = parsedCS.fullId; + } + + label = label || `${id} (${getExperienceFromApi(api).shortName})`; + treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); + } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { + const parsedPostgresConnString = parsePostgresConnectionString(connectionString); + treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); + } else { + const parsedCS = parseDocDBConnectionString(connectionString); + + label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; + switch (api) { + case API.Table: + treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); + break; + case API.Graph: + treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); + break; + case API.Core: + treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); + break; + default: + throw new Error(`Unexpected defaultExperience "${api}".`); + } + } + + treeItem.contextValue += AttachedAccountSuffix; + return treeItem; + } + + private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { + const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { + let api: API; + let isEmulator: boolean | undefined; + if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { + isEmulator = node.root.isEmulator; + } + if (node instanceof MongoAccountTreeItem) { + api = API.MongoDB; + } else if (node instanceof GraphAccountTreeItem) { + api = API.Graph; + } else if (node instanceof TableAccountTreeItem) { + api = API.Table; + } else if (node instanceof DocDBAccountTreeItem) { + api = API.Core; + } else if (node instanceof PostgresServerTreeItem) { + api = API.PostgresSingle; + } else { + throw new Error(`Unexpected account node "${node.constructor.name}".`); + } + return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; + }); + await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); + } } class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error( - "Cannot retrieve Azure subscription information for an attached account." - ); + private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); - public get credentials(): never { - throw this._error; - } + public get credentials(): never { + throw this._error; + } - public get subscriptionDisplayName(): never { - throw this._error; - } + public get subscriptionDisplayName(): never { + throw this._error; + } - public get subscriptionId(): never { - throw this._error; - } + public get subscriptionId(): never { + throw this._error; + } - public get subscriptionPath(): never { - throw this._error; - } + public get subscriptionPath(): never { + throw this._error; + } - public get tenantId(): never { - throw this._error; - } + public get tenantId(): never { + throw this._error; + } - public get userId(): never { - throw this._error; - } + public get userId(): never { + throw this._error; + } - public get environment(): never { - throw this._error; - } + public get environment(): never { + throw this._error; + } - public get isCustomCloud(): never { - throw this._error; - } + public get isCustomCloud(): never { + throw this._error; + } } async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/tree/AzureAccountTreeItemWithAttached.ts b/Source/tree/AzureAccountTreeItemWithAttached.ts index ce1cdb8fd..172cd598f 100644 --- a/Source/tree/AzureAccountTreeItemWithAttached.ts +++ b/Source/tree/AzureAccountTreeItemWithAttached.ts @@ -3,49 +3,34 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureAccountTreeItemBase } from "@microsoft/vscode-azext-azureutils"; -import { - AzExtTreeItem, - IActionContext, - ISubscriptionContext, -} from "@microsoft/vscode-azext-utils"; -import { ext } from "../extensionVariables"; -import { AttachedAccountsTreeItem } from "./AttachedAccountsTreeItem"; -import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; +import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; +import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; +import { ext } from '../extensionVariables'; +import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; +import { SubscriptionTreeItem } from './SubscriptionTreeItem'; export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } + public constructor(testAccount?: {}) { + super(undefined, testAccount); + ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); + } - public createSubscriptionTreeItem( - root: ISubscriptionContext - ): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } + public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { + return new SubscriptionTreeItem(this, root); + } - public async loadMoreChildrenImpl( - clearCache: boolean, - context: IActionContext - ): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl( - clearCache, - context - ); - return children.concat(ext.attachedAccountsNode); - } + public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { + const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); + return children.concat(ext.attachedAccountsNode); + } - public compareChildrenImpl( - item1: AzExtTreeItem, - item2: AzExtTreeItem - ): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } + public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { + if (item1 instanceof AttachedAccountsTreeItem) { + return 1; + } else if (item2 instanceof AttachedAccountsTreeItem) { + return -1; + } else { + return super.compareChildrenImpl(item1, item2); + } + } } diff --git a/Source/tree/AzureDBAPIStep.ts b/Source/tree/AzureDBAPIStep.ts index a59ebfd48..8a11fdc95 100644 --- a/Source/tree/AzureDBAPIStep.ts +++ b/Source/tree/AzureDBAPIStep.ts @@ -3,103 +3,74 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VerifyProvidersStep } from "@microsoft/vscode-azext-azureutils"; -import { - AzureWizardExecuteStep, - AzureWizardPromptStep, - IAzureQuickPickItem, - IWizardOptions, -} from "@microsoft/vscode-azext-utils"; -import { - API, - Experience, - getExperienceQuickPicks, -} from "../AzureDBExperiences"; -import { PostgresServerType } from "../postgres/abstract/models"; -import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; -import { PostgresServerConfirmPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep"; -import { PostgresServerCreateStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep"; -import { PostgresServerCredPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep"; -import { PostgresServerCredUserStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep"; -import { PostgresServerNameStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerNameStep"; -import { PostgresServerSetCredentialsStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep"; -import { PostgresServerSkuStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep"; -import { localize } from "../utils/localize"; -import { CosmosDBAccountCapacityStep } from "./CosmosDBAccountWizard/CosmosDBAccountCapacityStep"; -import { CosmosDBAccountCreateStep } from "./CosmosDBAccountWizard/CosmosDBAccountCreateStep"; -import { CosmosDBAccountNameStep } from "./CosmosDBAccountWizard/CosmosDBAccountNameStep"; -import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; -import { IAzureDBWizardContext } from "./IAzureDBWizardContext"; +import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; +import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; +import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; +import { PostgresServerType } from '../postgres/abstract/models'; +import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; +import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; +import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; +import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; +import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; +import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; +import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; +import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; +import { localize } from '../utils/localize'; +import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; +import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; +import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; +import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; +import { IAzureDBWizardContext } from './IAzureDBWizardContext'; -export class AzureDBAPIStep extends AzureWizardPromptStep< - IPostgresServerWizardContext | ICosmosDBWizardContext -> { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = - getExperienceQuickPicks(); +export class AzureDBAPIStep extends AzureWizardPromptStep { + public async prompt(context: IAzureDBWizardContext): Promise { + const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); - const result: IAzureQuickPickItem = - await context.ui.showQuickPick(picks, { - placeHolder: localize( - "selectDBServerMsg", - "Select an Azure Database Server." - ), - }); + const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { + placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') + }); - context.defaultExperience = result.data; - } + context.defaultExperience = result.data; + } - public async getSubWizard( - context: IAzureDBWizardContext - ): Promise< - IWizardOptions - > { - let promptSteps: AzureWizardPromptStep< - IPostgresServerWizardContext | ICosmosDBWizardContext - >[]; - let executeSteps: AzureWizardExecuteStep< - IPostgresServerWizardContext | ICosmosDBWizardContext - >[]; - if ( - context.defaultExperience?.api === API.PostgresSingle || - context.defaultExperience?.api === API.PostgresFlexible - ) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = - PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = - PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(["Microsoft.DBforPostgreSQL"]), - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(["Microsoft.DocumentDB"]), - ]; - } - return { promptSteps, executeSteps }; - } + public async getSubWizard(context: IAzureDBWizardContext): Promise> { + let promptSteps: AzureWizardPromptStep[]; + let executeSteps: AzureWizardExecuteStep[]; + if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { + switch (context.defaultExperience?.api) { + case API.PostgresFlexible: + (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; + break; + case API.PostgresSingle: + (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; + break; + } + promptSteps = [ + new PostgresServerNameStep(), + new PostgresServerSkuStep(), + new PostgresServerCredUserStep(), + new PostgresServerCredPWStep(), + new PostgresServerConfirmPWStep(), + ]; + executeSteps = [ + new PostgresServerCreateStep(), + new PostgresServerSetCredentialsStep(), + new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) + ]; + } else { + promptSteps = [ + new CosmosDBAccountNameStep(), + new CosmosDBAccountCapacityStep(), + ]; + executeSteps = [ + new CosmosDBAccountCreateStep(), + new VerifyProvidersStep(['Microsoft.DocumentDB']) + ]; + } + return { promptSteps, executeSteps }; + } - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } + public shouldPrompt(context: IAzureDBWizardContext): boolean { + return !context.defaultExperience; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts index 192e5fa54..b46453e3a 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts @@ -3,53 +3,38 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - AzureWizardPromptStep, - IAzureQuickPickItem, -} from "@microsoft/vscode-azext-utils"; -import { localize } from "../../utils/localize"; -import { openUrl } from "../../utils/openUrl"; -import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; +import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import { localize } from '../../utils/localize'; +import { openUrl } from '../../utils/openUrl'; +import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { - public async prompt(context: ICosmosDBWizardContext): Promise { - const placeHolder: string = localize( - "selectDBServerMsg", - "Select a capacity model." - ); - const picks: IAzureQuickPickItem[] = [ - { - label: localize("provisionedOption", "Provisioned Throughput"), - data: false, - }, - { label: localize("serverlessOption", "Serverless"), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { - label: localize("learnMore", "$(link-external) Learn more..."), - data: undefined, - }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; - do { - pick = await context.ui.showQuickPick(picks, { - placeHolder, - suppressPersistence: true, - }); - if (pick === learnMore) { - await openUrl("https://aka.ms/cosmos-models"); - } - } while (pick === learnMore); + public async prompt(context: ICosmosDBWizardContext): Promise { - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data - ? "true" - : "false"; - } - } + const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') + const picks: IAzureQuickPickItem[] = [ + { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, + { label: localize('serverlessOption', 'Serverless'), data: true }, + ]; + const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; + picks.push(learnMore); + let pick: IAzureQuickPickItem; - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } + do { + pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); + if (pick === learnMore) { + await openUrl('https://aka.ms/cosmos-models'); + } + } while (pick === learnMore); + + if (pick.data) { + context.isServerless = pick.data; + context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; + } + } + + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return context.isServerless === undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts index f0eadf3a3..4bd469b84 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts @@ -3,81 +3,61 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountCreateUpdateParameters } from "@azure/arm-cosmosdb/src/models"; -import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from "vscode"; -import { SERVERLESS_CAPABILITY_NAME } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { createCosmosDBClient } from "../../utils/azureClients"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from "../../utils/nonNull"; -import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; +import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; +import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; +import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; +import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; +import { Progress } from 'vscode'; +import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; +import { ext } from '../../extensionVariables'; +import { createCosmosDBClient } from '../../utils/azureClients'; +import { localize } from '../../utils/localize'; +import { nonNullProp } from '../../utils/nonNull'; +import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute( - context: ICosmosDBWizardContext, - progress: Progress<{ message?: string; increment?: number }> - ): Promise { - const locationName: string = ( - await LocationListStep.getLocation(context) - ).name; - const defaultExperience = nonNullProp(context, "defaultExperience"); - const rgName: string = nonNullProp( - nonNullProp(context, "resourceGroup"), - "name" - ); - const accountName = nonNullProp(context, "newServerName"); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize( - "creatingCosmosDBAccount", - 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', - accountName, - defaultExperience.shortName - ); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: "Standard", - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, "tag") }, - }; - - if (defaultExperience?.api === "MongoDB") { - options.apiProperties = { serverVersion: "3.6" }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = - await client.databaseAccounts.beginCreateOrUpdateAndWait( - rgName, - accountName, - options - ); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog( - `Successfully created Cosmos DB account "${accountName}".` - ); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } + public priority: number = 130; + + public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + const locationName: string = (await LocationListStep.getLocation(context)).name; + const defaultExperience = nonNullProp(context, 'defaultExperience'); + const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); + const accountName = nonNullProp(context, 'newServerName'); + + const client = await createCosmosDBClient(context); + const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); + ext.outputChannel.appendLog(creatingMessage); + progress.report({ message: creatingMessage }); + + const options: DatabaseAccountCreateUpdateParameters = { + location: locationName, + locations: [{ locationName: locationName }], + kind: defaultExperience.kind, + capabilities: [], + databaseAccountOfferType: 'Standard', + // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior + tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, + }; + + if (defaultExperience?.api === 'MongoDB') { + options.apiProperties = { serverVersion: '3.6' }; + } + + if (defaultExperience.capability) { + options.capabilities?.push({ name: defaultExperience.capability }); + } + + if (context.isServerless) { + options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); + } + + context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); + context.activityResult = context.databaseAccount as AppResource; + + ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); + } + + public shouldExecute(context: ICosmosDBWizardContext): boolean { + return !context.databaseAccount; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts index 222736605..87ef6be61 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts @@ -3,62 +3,47 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { - ResourceGroupListStep, - resourceGroupNamingRules, -} from "@microsoft/vscode-azext-azureutils"; -import { AzureNameStep } from "@microsoft/vscode-azext-utils"; -import { createCosmosDBClient } from "../../utils/azureClients"; -import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; +import { AzureNameStep } from '@microsoft/vscode-azext-utils'; +import { createCosmosDBClient } from '../../utils/azureClients'; +import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; export class CosmosDBAccountNameStep extends AzureNameStep { - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = ( - await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => - validateCosmosDBAccountName(name, client), - }) - ).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName( - context, - context.newServerName, - resourceGroupNamingRules - ); - } - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } + public async prompt(context: ICosmosDBWizardContext): Promise { + const client = await createCosmosDBClient(context); + context.newServerName = (await context.ui.showInputBox({ + placeHolder: "Account name", + prompt: "Provide a Cosmos DB account name", + validateInput: (name: string) => validateCosmosDBAccountName(name, client) + })).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); + } - protected async isRelatedNameAvailable( - context: ICosmosDBWizardContext, - name: string - ): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return !context.newServerName; + } + + protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validateCosmosDBAccountName( - name: string, - client: CosmosDBManagementClient -): Promise { - name = name ? name.trim() : ""; +async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { + name = name ? name.trim() : ''; - const min = 3; - const max = 31; + const min = 3; + const max = 31; - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } + if (name.length < min || name.length > max) { + return `The name must be between ${min} and ${max} characters.`; + } else if (name.match(/[^a-z0-9-]/)) { + return "The name can only contain lowercase letters, numbers, and the '-' character."; + } else if ((await client.databaseAccounts.checkNameExists(name)).body) { + return `Account name "${name}" is not available.`; + } else { + return undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts index cc12a75ed..61666a859 100644 --- a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb"; -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { IAzureDBWizardContext } from "../IAzureDBWizardContext"; +import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; +import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; +import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; + +export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { + + /** + * The newly created Cosmos DB account + * This will be defined after `CosmosDBAccountStep.execute` occurs. + */ + databaseAccount?: DatabaseAccountGetResults; + isServerless?: boolean; -export interface ICosmosDBWizardContext - extends IAzureDBWizardContext, - ExecuteActivityContext { - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; } diff --git a/Source/tree/IAzureDBWizardContext.ts b/Source/tree/IAzureDBWizardContext.ts index 5f6946275..fd84ff0d5 100644 --- a/Source/tree/IAzureDBWizardContext.ts +++ b/Source/tree/IAzureDBWizardContext.ts @@ -3,10 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; -import { Experience } from "../AzureDBExperiences"; +import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; +import { Experience } from '../AzureDBExperiences'; export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - newServerName?: string; - defaultExperience?: Experience; + + newServerName?: string; + defaultExperience?: Experience; + } diff --git a/Source/tree/SubscriptionTreeItem.ts b/Source/tree/SubscriptionTreeItem.ts index 93cb2173a..910d8d970 100644 --- a/Source/tree/SubscriptionTreeItem.ts +++ b/Source/tree/SubscriptionTreeItem.ts @@ -3,322 +3,156 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { - DatabaseAccountGetResults, - DatabaseAccountListKeysResult, -} from "@azure/arm-cosmosdb/src/models"; -import { - getResourceGroupFromId, - ILocationWizardContext, - LocationListStep, - ResourceGroupListStep, - SubscriptionTreeItemBase, - uiUtils, -} from "@microsoft/vscode-azext-azureutils"; -import { - AzExtParentTreeItem, - AzExtTreeItem, - AzureWizard, - AzureWizardPromptStep, - IActionContext, -} from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { - API, - Experience, - getExperienceLabel, - tryGetExperience, -} from "../AzureDBExperiences"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; +import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; +import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from "../extensionVariables"; -import { tryGetGremlinEndpointFromAzure } from "../graph/gremlinEndpoints"; +import { ext } from '../extensionVariables'; +import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { - PostgresAbstractServer, - PostgresServerType, -} from "../postgres/abstract/models"; -import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; -import { - createPostgresConnectionString, - ParsedPostgresConnectionString, - parsePostgresConnectionString, -} from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; +import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; +import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; +import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; +import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; +import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from "../utils/activityUtils"; -import { - createCosmosDBClient, - createPostgreSQLClient, - createPostgreSQLFlexibleClient, -} from "../utils/azureClients"; -import { localize } from "../utils/localize"; -import { nonNullProp } from "../utils/nonNull"; -import { AzureDBAPIStep } from "./AzureDBAPIStep"; -import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; +import { createActivityContext } from '../utils/activityUtils'; +import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; +import { localize } from '../utils/localize'; +import { nonNullProp } from '../utils/nonNull'; +import { AzureDBAPIStep } from './AzureDBAPIStep'; +import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = "Account"; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl( - _clearCache: boolean, - context: IActionContext - ): Promise { - //Postgres - const postgresSingleClient = await createPostgreSQLClient([ - context, - this.subscription, - ]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([ - context, - this.subscription, - ]); - const postgresServers: PostgresAbstractServer[] = [ - ...( - await uiUtils.listAllIterator( - postgresSingleClient.servers.list() - ) - ).map((s) => - Object.assign(s, { serverType: PostgresServerType.Single }) - ), - ...( - await uiUtils.listAllIterator( - postgresFlexibleClient.servers.list() - ) - ).map((s) => - Object.assign(s, { serverType: PostgresServerType.Flexible }) - ), - ]; - - const treeItemPostgres: AzExtTreeItem[] = - await this.createTreeItemsWithErrorHandling( - postgresServers, - "invalidPostgreSQLAccount", - async (server: PostgresAbstractServer) => - await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator( - client.databaseAccounts.list() - ); - const treeItem: AzExtTreeItem[] = - await this.createTreeItemsWithErrorHandling( - accounts, - "invalidCosmosDBAccount", - async (db: DatabaseAccountGetResults) => - await SubscriptionTreeItem.initCosmosDBChild( - client, - db, - this - ), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild( - context: IActionContext & { defaultExperience?: Experience }, - node: SubscriptionTreeItem - ): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & - ICosmosDBWizardContext = Object.assign(context, node.subscription, { - ...(await createActivityContext()), - }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep(), - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize( - "createDBServerMsg", - "Create new Azure Database Server" - ), - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = - wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp( - wizardContext, - "newServerName" - ); - wizardContext.activityTitle = localize( - "createDBServerMsgActivityTitle", - 'Create new Azure Database Server "{0}"', - newServerName - ); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if ( - wizardContext.defaultExperience?.api === API.PostgresSingle || - wizardContext.defaultExperience?.api === API.PostgresFlexible - ) { - const createMessage: string = localize( - "createdServerOutput", - 'Successfully created PostgreSQL server "{0}".', - wizardContext.newServerName - ); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, "server"); - const host = nonNullProp(server, "fullyQualifiedDomainName"); - const username: string = - wizardContext.serverType === PostgresServerType.Flexible - ? nonNullProp(wizardContext, "shortUserName") - : nonNullProp(wizardContext, "longUserName"); - const password: string = nonNullProp( - wizardContext, - "adminPassword" - ); - const connectionString: string = createPostgresConnectionString( - host, - undefined, - username, - password - ); - const parsedCS: ParsedPostgresConnectionString = - parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild( - client, - nonNullProp(wizardContext, "databaseAccount"), - node - ); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return ( - typeof contextValue !== "string" || !/attached/i.test(contextValue) - ); - } - - public static async initCosmosDBChild( - client: CosmosDBManagementClient, - databaseAccount: DatabaseAccountGetResults, - parent: AzExtParentTreeItem - ): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, "id"); - const name: string = nonNullProp(databaseAccount, "name"); - const documentEndpoint: string = nonNullProp( - databaseAccount, - "documentEndpoint" - ); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = - name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings( - resourceGroup, - name - ); - const connectionString: URL = new URL( - nonNullProp( - nonNullProp(result, "connectionStrings")[0], - "connectionString" - ) - ); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = "retrywrites"; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, "false"); - } - - // Use the default connection string - return new MongoAccountTreeItem( - parent, - id, - label, - connectionString.toString(), - isEmulator, - databaseAccount - ); - } else { - const keyResult: DatabaseAccountListKeysResult = - await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp( - keyResult, - "primaryMasterKey" - ); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem( - parent, - id, - label, - documentEndpoint, - primaryMasterKey, - isEmulator, - databaseAccount - ); - case "Graph": { - const gremlinEndpoint = - await tryGetGremlinEndpointFromAzure( - client, - resourceGroup, - name - ); - return new GraphAccountTreeItem( - parent, - id, - label, - documentEndpoint, - gremlinEndpoint, - primaryMasterKey, - isEmulator, - databaseAccount - ); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem( - parent, - id, - label, - documentEndpoint, - primaryMasterKey, - isEmulator, - databaseAccount - ); - } - } - } - public static async initPostgresChild( - server: PostgresAbstractServer, - parent: AzExtParentTreeItem - ): Promise { - const connectionString: string = createPostgresConnectionString( - nonNullProp(server, "fullyQualifiedDomainName") - ); - const parsedCS: ParsedPostgresConnectionString = - parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } + public childTypeLabel: string = 'Account'; + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { + + //Postgres + const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); + const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); + const postgresServers: PostgresAbstractServer[] = [ + ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), + ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), + ]; + + const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( + postgresServers, + 'invalidPostgreSQLAccount', + async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), + (server: PostgresAbstractServer) => server.name + ); + + //CosmosDB + const client = await createCosmosDBClient([context, this]); + const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); + const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( + accounts, + 'invalidCosmosDBAccount', + async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), + (db: DatabaseAccountGetResults) => db.name + ); + + treeItem.push(...treeItemPostgres); + return treeItem; + } + + public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { + const client = await createCosmosDBClient([context, node.subscription]); + const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); + + const promptSteps: AzureWizardPromptStep[] = [ + new AzureDBAPIStep(), + new ResourceGroupListStep() + ]; + LocationListStep.addStep(wizardContext, promptSteps); + + const wizard = new AzureWizard(wizardContext, { + promptSteps, + executeSteps: [], + title: localize('createDBServerMsg', 'Create new Azure Database Server') + }); + + await wizard.prompt(); + + wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; + + const newServerName: string = nonNullProp(wizardContext, 'newServerName'); + wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); + + await wizard.execute(); + await ext.rgApi.appResourceTree.refresh(context); + if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { + const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); + const server = nonNullProp(wizardContext, 'server'); + const host = nonNullProp(server, 'fullyQualifiedDomainName'); + const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); + const password: string = nonNullProp(wizardContext, 'adminPassword'); + const connectionString: string = createPostgresConnectionString(host, undefined, username, password); + const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(node, parsedCS, server); + } else { + return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); + } + } + + public isAncestorOfImpl(contextValue: string | RegExp): boolean { + return typeof contextValue !== 'string' || !/attached/i.test(contextValue); + } + + public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { + const experience = tryGetExperience(databaseAccount); + const id: string = nonNullProp(databaseAccount, 'id'); + const name: string = nonNullProp(databaseAccount, 'name'); + const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); + + const resourceGroup: string = getResourceGroupFromId(id); + const accountKindLabel = getExperienceLabel(databaseAccount); + const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); + const isEmulator: boolean = false; + + if (experience && experience.api === "MongoDB") { + const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); + const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); + // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites + // but the newer node.js drivers started breaking this + const searchParam: string = 'retrywrites'; + if (!connectionString.searchParams.has(searchParam)) { + connectionString.searchParams.set(searchParam, 'false'); + } + + // Use the default connection string + return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); + } else { + const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); + const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); + switch (experience && experience.api) { + case "Table": + return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); + case "Graph": { + const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); + return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); + } + case "Core": + default: + // Default to DocumentDB, the base type for all Cosmos DB Accounts + return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); + + } + } + } + public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { + const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); + const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(parent, parsedCS, server); + } } diff --git a/Source/utils/InteractiveChildProcess.ts b/Source/utils/InteractiveChildProcess.ts index 1cd1848e5..26129b342 100644 --- a/Source/utils/InteractiveChildProcess.ts +++ b/Source/utils/InteractiveChildProcess.ts @@ -3,194 +3,174 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as cp from "child_process"; -import * as os from "os"; -import { isNumber } from "util"; -import * as vscode from "vscode"; -import { Event, EventEmitter } from "vscode"; -import { improveError } from "./improveError"; +import { parseError } from '@microsoft/vscode-azext-utils'; +import * as cp from 'child_process'; +import * as os from 'os'; +import { isNumber } from 'util'; +import * as vscode from 'vscode'; +import { Event, EventEmitter } from 'vscode'; +import { improveError } from './improveError'; // We add these when we display to the output window -const stdInPrefix = "> "; -const stdErrPrefix = "ERR> "; -const errorPrefix = "Error running process: "; +const stdInPrefix = '> '; +const stdErrPrefix = 'ERR> '; +const errorPrefix = 'Error running process: '; const processStartupTimeout = 60; export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; + command: string; + args: string[]; + outputChannel?: vscode.OutputChannel; + workingDirectory?: string; + showTimeInOutputChannel?: boolean; + outputFilterSearch?: RegExp; + outputFilterReplace?: string; } export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = - new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = - new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = - new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create( - options: IInteractiveChildProcessOptions - ): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess( - options - ); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(" "); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false, - }; - - this.writeLineToOutputChannel( - `Starting executable: "${this._options.command}" ${formattedArgs}` - ); - this._childProc = cp.spawn( - this._options.command, - this._options.args, - options - ); - - this._childProc.stdout?.on("data", (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on("data", (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on("error", (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on("close", (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel( - text: string, - displayPrefix?: string - ): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = - filteredText !== text && filteredText === ""; - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace( - this._options.outputFilterSearch, - this._options.outputFilterReplace || "" - ); - } - - return text; - } + private _childProc: cp.ChildProcess; + private readonly _options: IInteractiveChildProcessOptions; + private _startTime: number; + private _error: unknown; + private _isKilling: boolean; + + private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); + private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); + private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); + + private constructor(options: IInteractiveChildProcessOptions) { + this._options = options; + } + + public get onStdOut(): Event { + return this._onStdOutEmitter.event; + } + + public get onStdErr(): Event { + return this._onStdErrEmitter.event; + } + + public get onError(): Event { + return this._onErrorEmitter.event; + } + + public static async create(options: IInteractiveChildProcessOptions): Promise { + const child: InteractiveChildProcess = new InteractiveChildProcess(options); + await child.startCore(); + return child; + } + + public kill(): void { + this._isKilling = true; + this._childProc.kill(); + } + + public writeLine(text: string): void { + this.writeLineToOutputChannel(text, stdInPrefix); + this._childProc.stdin?.write(text + os.EOL); + } + + private async startCore(): Promise { + this._startTime = Date.now(); + const formattedArgs: string = this._options.args.join(' '); + + const workingDirectory = this._options.workingDirectory || os.tmpdir(); + const options: cp.SpawnOptions = { + cwd: workingDirectory, + + // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since + // the command is run in the shell, handling errors (such as command not found) would be more indirect, + // coming through STDERR instead of the error event + shell: false + }; + + this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); + this._childProc = cp.spawn(this._options.command, this._options.args, options); + + this._childProc.stdout?.on('data', (data: string | Buffer) => { + const text = data.toString(); + this._onStdOutEmitter.fire(text); + this.writeLineToOutputChannel(text); + }); + + this._childProc.stderr?.on('data', (data: string | Buffer) => { + const text = data.toString(); + this._onStdErrEmitter.fire(text); + this.writeLineToOutputChannel(text, stdErrPrefix); + }); + + this._childProc.on('error', (error: unknown) => { + const improvedError = improveError(error); + this.setError(improvedError); + }); + + this._childProc.on('close', (code: number | null) => { + if (isNumber(code) && code !== 0) { + this.setError(`The process exited with code ${code}.`); + } else if (!this._isKilling) { + this.setError(`The process exited prematurely.`); + } + }); + + // Wait for the process to start up + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + await new Promise(async (resolve, reject) => { + const started = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + if (!!this._error || this._isKilling) { + reject(this._error); + break; + } else if (this._childProc.pid) { + resolve(); + break; + } else { + if (Date.now() > started + processStartupTimeout) { + reject("The process did not start in a timely manner"); + break; + } + await delay(50); + } + } + }); + } + + private writeLineToOutputChannel(text: string, displayPrefix?: string): void { + const filteredText = this.filterText(text); + const changedIntoEmptyString = (filteredText !== text && filteredText === ''); + + if (!changedIntoEmptyString) { + text = filteredText; + if (this._options.outputChannel) { + if (this._options.showTimeInOutputChannel) { + const ms = Date.now() - this._startTime; + text = `${ms}ms: ${text}`; + } + + text = (displayPrefix || "") + text; + this._options.outputChannel.appendLine(text); + } + } + } + + private setError(error: unknown): void { + this.writeLineToOutputChannel(parseError(error).message, errorPrefix); + this._error = this._error || error; + this._onErrorEmitter.fire(error); + } + + private filterText(text: string): string { + if (this._options.outputFilterSearch) { + return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); + } + + return text; + } } async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/utils/activityUtils.ts b/Source/utils/activityUtils.ts index d90c436cd..fefd2fe00 100644 --- a/Source/utils/activityUtils.ts +++ b/Source/utils/activityUtils.ts @@ -8,13 +8,8 @@ import { ext } from "../extensionVariables"; import { getWorkspaceSetting } from "./settingUtils"; export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => - ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting( - "suppressActivityNotifications", - undefined, - "azureResourceGroups" - ), - }; + return { + registerActivity: async (activity) => ext.rgApi.registerActivity(activity), + suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), + }; } diff --git a/Source/utils/array.ts b/Source/utils/array.ts index 5d779a53a..06f095e8d 100644 --- a/Source/utils/array.ts +++ b/Source/utils/array.ts @@ -4,21 +4,11 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType( - arr: Object[] | undefined, - genericConstructor: new (...args: any[]) => T -): T[] { - return arr - ? arr.filter((element) => element instanceof genericConstructor) - : []; +export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { + return arr ? arr.filter(element => element instanceof genericConstructor) : []; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType( - arr: Object[] | undefined, - genericConstructor: new (...args: any[]) => T -): T | undefined { - return ( - arr && arr.find((element) => element instanceof genericConstructor) - ); +export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { + return arr && arr.find(element => element instanceof genericConstructor); } diff --git a/Source/utils/azureClients.ts b/Source/utils/azureClients.ts index c2f44bd1c..9be19e959 100644 --- a/Source/utils/azureClients.ts +++ b/Source/utils/azureClients.ts @@ -3,41 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; -import { PostgreSQLManagementClient } from "@azure/arm-postgresql"; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; -import { - AzExtClientContext, - createAzureClient, -} from "@microsoft/vscode-azext-azureutils"; +import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; +import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; +import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; +import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript -export async function createCosmosDBClient( - context: AzExtClientContext -): Promise { - return createAzureClient( - context, - (await import("@azure/arm-cosmosdb")).CosmosDBManagementClient - ); +export async function createCosmosDBClient(context: AzExtClientContext): Promise { + return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); } -export async function createPostgreSQLClient( - context: AzExtClientContext -): Promise { - return createAzureClient( - context, - (await import("@azure/arm-postgresql")).PostgreSQLManagementClient - ); +export async function createPostgreSQLClient(context: AzExtClientContext): Promise { + return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); } -export async function createPostgreSQLFlexibleClient( - context: AzExtClientContext -): Promise { - return createAzureClient( - context, - (await import("@azure/arm-postgresql-flexible")) - .PostgreSQLManagementClient - ); +export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { + return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); } diff --git a/Source/utils/azureUtils.ts b/Source/utils/azureUtils.ts index 0e067aa68..b0017314b 100644 --- a/Source/utils/azureUtils.ts +++ b/Source/utils/azureUtils.ts @@ -4,13 +4,11 @@ *--------------------------------------------------------------------------------------------*/ export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match( - /\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/ - ); + const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); - if (!matches || matches.length < 5) { - throw new Error("Invalid Azure Resource Id"); - } + if (!matches || matches.length < 5) { + throw new Error('Invalid Azure Resource Id'); + } - return matches[4]; + return matches[4]; } diff --git a/Source/utils/cp.ts b/Source/utils/cp.ts index 7f7d94117..660dc3068 100644 --- a/Source/utils/cp.ts +++ b/Source/utils/cp.ts @@ -3,15 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from "child_process"; +import * as cp from 'child_process'; -export async function commandSucceeds( - command: string, - ...args: string[] -): Promise { - return await new Promise((resolve) => { - cp.spawn(command, args) - .on("error", (_error) => resolve(false)) - .on("exit", (code) => resolve(code === 0)); - }); +export async function commandSucceeds(command: string, ...args: string[]): Promise { + return await new Promise(resolve => { + cp.spawn(command, args) + .on('error', _error => resolve(false)) + .on('exit', code => resolve(code === 0)); + }); } diff --git a/Source/utils/getIp.ts b/Source/utils/getIp.ts index d3085ea52..20d22e989 100644 --- a/Source/utils/getIp.ts +++ b/Source/utils/getIp.ts @@ -1,73 +1,61 @@ /*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from "@microsoft/vscode-azext-azureutils"; -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { isIPv4 } from "net"; -import { localize } from "./localize"; - -export function isIpInRanges( - ip: string, - ranges: { startIpAddress: string; endIpAddress: string }[] -): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ + +import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import { isIPv4 } from 'net'; +import { localize } from './localize'; + +export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { + const ipNum = ipToNum(ip); + return ranges.some((range) => { + const startIpNum = ipToNum(range.startIpAddress); + const endIpNum = ipToNum(range.endIpAddress); + return startIpNum <= ipNum && ipNum <= endIpNum; + }); } export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, "https://api.ipify.org/"), - () => getPublicIpv4Https(context, "https://ipv4.icanhazip.com/"), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; + const methods: (() => Promise)[] = [ + () => getPublicIpv4Https(context, 'https://api.ipify.org/'), + () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), + ]; + + let lastError: unknown; + for (const getIp of methods) { + try { + return await getIp(); + } catch (e: unknown) { + lastError = e; + } + } + + throw lastError; } -const failedToGetIp = localize("failedToGetIp", "Failed to get public IP"); +const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); function ipToNum(ip: string) { - return Number( - ip - .split(".") - .map((d) => ("000" + d).substring(-3)) - .join("") - ); + return Number( + ip.split(".") + .map(d => ("000" + d).substring(-3)) + .join("") + ); } -async function getPublicIpv4Https( - context: IActionContext, - url: string -): Promise { - const req = await sendRequestWithTimeout( - context, - { - method: "GET", - url, - }, - 5000, - undefined - ); +async function getPublicIpv4Https(context: IActionContext, url: string): Promise { + const req = await sendRequestWithTimeout(context, { + method: 'GET', + url, + }, 5000, undefined); - const ip = req.bodyAsText; + const ip = req.bodyAsText; - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } + if (!ip || !isIPv4(ip)) { + throw new Error(failedToGetIp); + } - return ip; + return ip; } diff --git a/Source/utils/getSecretStorageKey.ts b/Source/utils/getSecretStorageKey.ts index d04de6cea..8e404f554 100644 --- a/Source/utils/getSecretStorageKey.ts +++ b/Source/utils/getSecretStorageKey.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; + return `${serviceName}.${id}`; } diff --git a/Source/utils/improveError.ts b/Source/utils/improveError.ts index 08f0bedaf..27ff1f014 100644 --- a/Source/utils/improveError.ts +++ b/Source/utils/improveError.ts @@ -6,12 +6,12 @@ import { parseError } from "@microsoft/vscode-azext-utils"; export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } + const message = parseError(error).message; + // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" + const match = message.match(/spawn (.*) ENOENT/); + if (match) { + return new Error(`Could not find ${match[1]}`); + } - return error; + return error; } diff --git a/Source/utils/localize.ts b/Source/utils/localize.ts index 76d8fbf4d..2aee3fa12 100644 --- a/Source/utils/localize.ts +++ b/Source/utils/localize.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from "vscode-nls"; +import * as nls from 'vscode-nls'; export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Source/utils/nonNull.ts b/Source/utils/nonNull.ts index e9437afc9..d7104b4f8 100644 --- a/Source/utils/nonNull.ts +++ b/Source/utils/nonNull.ts @@ -3,52 +3,39 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { isNullOrUndefined } from "util"; +import { isNullOrUndefined } from 'util'; /** * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed * for the property and will give a compile error if the given name is not a property of the source. */ -export function nonNullProp( - source: TSource, - name: TKey -): NonNullable { - const value: NonNullable = >( - source[name] - ); - return nonNullValue(value, name); +export function nonNullProp(source: TSource, name: TKey): NonNullable { + const value: NonNullable = >source[name]; + return nonNullValue(value, name); } /** * Validates that a given value is not null and not undefined. */ -export function nonNullValue( - value: T | undefined | null, - propertyNameOrMessage?: string -): T { - if (isNullOrUndefined(value)) { - throw new Error( - "Internal error: Expected value to be neither null nor undefined" + - (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") - ); - } +export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { + if (isNullOrUndefined(value)) { + throw new Error( + 'Internal error: Expected value to be neither null nor undefined' + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); + } - return value; + return value; } /** * Validates that a given string is not null, undefined, nor empty */ -export function nonNullOrEmptyValue( - value: string | undefined, - propertyNameOrMessage?: string -): string { - if (!value) { - throw new Error( - "Internal error: Expected value to be neither null, undefined, nor empty" + - (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") - ); - } +export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { + if (!value) { + throw new Error( + 'Internal error: Expected value to be neither null, undefined, nor empty' + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); + } - return value; + return value; } diff --git a/Source/utils/openUrl.ts b/Source/utils/openUrl.ts index 5c7deaca7..0be3f5bbb 100644 --- a/Source/utils/openUrl.ts +++ b/Source/utils/openUrl.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as open from "open"; +import * as open from 'open'; export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); + // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 + // await vscode.env.openExternal(vscode.Uri.parse(url)); - await open(url); + await open(url); } diff --git a/Source/utils/randomUtils.ts b/Source/utils/randomUtils.ts index 1c4856b09..7a313f23a 100644 --- a/Source/utils/randomUtils.ts +++ b/Source/utils/randomUtils.ts @@ -6,15 +6,12 @@ import * as crypto from "crypto"; export namespace randomUtils { - export function getPseudononymousStringHash( - s: string, - encoding: crypto.BinaryToTextEncoding = "base64" - ): string { - return crypto.createHash("sha256").update(s).digest(encoding); - } + export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { + return crypto.createHash('sha256').update(s).digest(encoding); + } - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString("hex").slice(0, length); - } + export function getRandomHexString(length: number): string { + const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); + return buffer.toString('hex').slice(0, length); + } } diff --git a/Source/utils/settingUtils.ts b/Source/utils/settingUtils.ts index 0f75feb17..0ac1004c2 100644 --- a/Source/utils/settingUtils.ts +++ b/Source/utils/settingUtils.ts @@ -3,98 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { - ConfigurationTarget, - Uri, - workspace, - WorkspaceConfiguration, -} from "vscode"; +import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; import { ext } from "../extensionVariables"; /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateGlobalSetting( - section: string, - value: T, - prefix: string = ext.prefix -): Promise { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix); - await projectConfiguration.update( - section, - value, - ConfigurationTarget.Global - ); +export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); + await projectConfiguration.update(section, value, ConfigurationTarget.Global); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateWorkspaceSetting( - section: string, - value: T, - fsPath: string, - prefix: string = ext.prefix -): Promise { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); +export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); + await projectConfiguration.update(section, value); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getGlobalSetting( - key: string, - prefix: string = ext.prefix -): T | undefined { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = - projectConfiguration.inspect(key); - return result && result.globalValue; +export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); + const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); + return result && result.globalValue; } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSetting( - key: string, - fsPath?: string, - prefix: string = ext.prefix -): T | undefined { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration( - prefix, - fsPath ? Uri.file(fsPath) : undefined - ); - return projectConfiguration.get(key); +export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); + return projectConfiguration.get(key); } /** * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSettingFromAnyFolder( - key: string, - prefix: string = ext.prefix -): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = - workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = - projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } +export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { + if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { + let result: string | undefined; + for (const folder of workspace.workspaceFolders) { + const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); + const folderResult: string | undefined = projectConfiguration.get(key); + if (!result) { + result = folderResult; + } else if (folderResult && result !== folderResult) { + return undefined; + } + } + return result; + } else { + return getGlobalSetting(key, prefix); + } } diff --git a/Source/utils/timeout.ts b/Source/utils/timeout.ts index 1645f6d3f..cc5ffb2d6 100644 --- a/Source/utils/timeout.ts +++ b/Source/utils/timeout.ts @@ -8,50 +8,44 @@ const timedOutMessage = "Execution timed out"; /** * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. */ -export async function valueOnTimeout( - timeoutMs: number, - timeoutValue: T, - action: () => Promise | T -): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } +export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { + try { + return await rejectOnTimeout(timeoutMs, action); + } catch (err) { + const error = <{ message?: string }>err; + if (error && error.message === timedOutMessage) { + return timeoutValue; + } - throw err; - } + throw err; + } } /** * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. */ -export async function rejectOnTimeout( - timeoutMs: number, - action: () => Promise | T, - callerTimeOutMessage?: string -): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout(() => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, timeoutMs); +export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + return await new Promise(async (resolve, reject) => { + let timer: NodeJS.Timer | undefined = setTimeout( + () => { + timer = undefined; + reject(new Error(callerTimeOutMessage || timedOutMessage)); + }, + timeoutMs); - let value: T; - let error; + let value: T; + let error; - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); + try { + value = await action(); + clearTimeout(timer); + resolve(value); + } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + error = err; + clearTimeout(timer); + reject(error); + } + }); } diff --git a/Source/utils/vscodeUtils.ts b/Source/utils/vscodeUtils.ts index bdb5665b5..d05f84872 100644 --- a/Source/utils/vscodeUtils.ts +++ b/Source/utils/vscodeUtils.ts @@ -3,145 +3,101 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from "@azure/cosmos"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import * as fse from "fs-extra"; -import * as path from "path"; -import * as vscode from "vscode"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { ext } from "../extensionVariables"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { IMongoDocument } from "../mongo/tree/MongoDocumentTreeItem"; -import { getRootPath } from "./workspacUtils"; +import { ItemDefinition } from '@azure/cosmos'; +import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; +import { ext } from '../extensionVariables'; +import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; +import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; +import { getRootPath } from './workspacUtils'; export interface IDisposable { - dispose(): void; + dispose(): void; } export function dispose(disposables: T[]): T[] { - disposables.forEach((d) => d.dispose()); - return []; + disposables.forEach(d => d.dispose()); + return []; } export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; + return { dispose }; } -export async function showNewFile( - data: string, - fileName: string, - fileExtension: string, - column?: vscode.ViewColumn -): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName( - folderPath, - fileName, - fileExtension - ); - const uri: vscode.Uri = vscode.Uri.file( - path.join(folderPath, fullFileName) - ).with({ scheme: "untitled" }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument( - textDocument, - column - ? column > vscode.ViewColumn.Three - ? vscode.ViewColumn.One - : column - : undefined, - true - ); - await writeToEditor(editor, data); +export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { + const folderPath: string = getRootPath() || ext.context.extensionPath; + const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); + const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); + const textDocument = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); + await writeToEditor(editor, data); } -export async function writeToEditor( - editor: vscode.TextEditor, - data: string -): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt( - editor.document.lineCount - 1 - ); - editBuilder.delete( - new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position( - lastLine.range.start.line, - lastLine.range.end.character - ) - ) - ); - } +export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { + await editor.edit((editBuilder: vscode.TextEditorEdit) => { + if (editor.document.lineCount > 0) { + const lastLine = editor.document.lineAt(editor.document.lineCount - 1); + editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); + } - editBuilder.insert(new vscode.Position(0, 0), data); - }); + editBuilder.insert(new vscode.Position(0, 0), data); + }); } -async function getUniqueFileName( - folderPath: string, - fileName: string, - fileExtension: string -): Promise { - let count: number = 1; - const maxCount: number = 1024; +async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { + let count: number = 1; + const maxCount: number = 1024; - while (count < maxCount) { - const fileSuffix = count === 0 ? "" : "-" + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; + while (count < maxCount) { + const fileSuffix = count === 0 ? '' : '-' + count.toString(); + const fullFileName: string = fileName + fileSuffix + fileExtension; - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = - vscode.workspace.textDocuments.find( - (doc) => doc.uri.fsPath === fullPath - ) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } + const fullPath: string = path.join(folderPath, fullFileName); + const pathExists: boolean = await fse.pathExists(fullPath); + const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; + if (!pathExists && !editorExists) { + return fullFileName; + } + count += 1; + } - throw new Error("Could not find unique name for new file."); + throw new Error('Could not find unique name for new file.'); } export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join("/"); + const labels = [node.label]; + while (node.parent) { + node = node.parent; + labels.unshift(node.label); + if (isAccountTreeItem(node)) { + break; + } + } + return labels.join('/'); } function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return ( - treeItem instanceof MongoAccountTreeItem || - treeItem instanceof DocDBAccountTreeItemBase - ); + return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); } -export function getDocumentTreeItemLabel( - document: IMongoDocument | ItemDefinition -): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== "object") { - return String(value); - } - } - } - return String(document._id); +export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { + for (const field of getDocumentLabelFields()) { + // eslint-disable-next-line no-prototype-builtins + if (document.hasOwnProperty(field)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const value = document[field]; + if (value !== undefined && typeof value !== 'object') { + return String(value); + } + } + } + return String(document._id); } function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; + const settingKey: string = ext.settingsKeys.documentLabelFields; + return vscode.workspace.getConfiguration().get(settingKey) || []; } diff --git a/Source/utils/workspacUtils.ts b/Source/utils/workspacUtils.ts index 6892c2f6d..20b60da11 100644 --- a/Source/utils/workspacUtils.ts +++ b/Source/utils/workspacUtils.ts @@ -3,23 +3,16 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from "vscode"; -import { ext } from "../extensionVariables"; -import { nonNullValue } from "./nonNull"; +import * as vscode from 'vscode'; +import { ext } from '../extensionVariables'; +import { nonNullValue } from './nonNull'; export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && - vscode.workspace.workspaceFolders.length === 1 - ? vscode.workspace.workspaceFolders[0].uri.fsPath - : undefined; + // if this is a multi-root workspace, return undefined + return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; } export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = - vscode.workspace.getConfiguration(); - return nonNullValue( - config.get(ext.settingsKeys.batchSize), - "batchSize" - ); + const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); + return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); } diff --git a/Source/utils/wrapError.ts b/Source/utils/wrapError.ts index b82f638fd..f6ec5d2b5 100644 --- a/Source/utils/wrapError.ts +++ b/Source/utils/wrapError.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from "os"; +import * as os from 'os'; export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } + if (!innerError) { + return outerError; + } else if (!outerError) { + return innerError; + } - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } + const innerMessage = parseError(innerError).message; + const outerMessage = parseError(outerError).message; + if (outerError instanceof Error) { + outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; + return outerError; + } - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); + return new Error(`${outerMessage}${os.EOL}${innerMessage}`); } diff --git a/Source/vscode-cosmosdb.api.d.ts b/Source/vscode-cosmosdb.api.d.ts index 4e813c5e5..d5e4416c1 100644 --- a/Source/vscode-cosmosdb.api.d.ts +++ b/Source/vscode-cosmosdb.api.d.ts @@ -4,103 +4,93 @@ *--------------------------------------------------------------------------------------------*/ export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem( - query: TreeItemQuery - ): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem( - options: PickTreeItemOptions & { resourceType: "DatabaseAccount" } - ): Promise; - pickTreeItem( - options: PickTreeItemOptions & { resourceType: "Database" } - ): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; + apiVersion: string; + + /** + * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. + * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. + * + * @param query The query object to use for the find + */ + findTreeItem(query: TreeItemQuery): Promise; + + /** + * Prompts the user to pick an item from the Azure Databases tree + * + * @param options Configures the behavior of the tree item picker + */ + pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; + pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; + + /** + * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string + */ + revealTreeItem(resourceId: string): Promise; } export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; + /** + * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. + */ + reveal(): Promise; } export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - }; - - docDBData?: { - masterKey: string; - documentEndpoint: string; - }; - - postgresData?: { - username: string | undefined; - password: string | undefined; - }; + hostName: string; + port: string; + connectionString: string; + + /** + * Data specific to Azure or undefined if the resource is not in Azure. + */ + azureData?: { + accountName: string; + accountId: string; + } + + docDBData?: { + masterKey: string; + documentEndpoint: string; + } + + postgresData?: { + username: string | undefined; + password: string | undefined; + } + } export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; + databaseName: string; } -export type AzureDatabasesResourceType = "DatabaseAccount" | "Database"; +export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; -export type AzureDatabasesApiType = - | "Mongo" - | "SQL" - | "Graph" - | "Table" - | "Postgres"; +export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; + /** + * The resource type of the picked item + */ + resourceType: AzureDatabasesResourceType; + + /** + * An array of the API types that can be picked, or undefined if all API types are allowed + */ + apiType?: AzureDatabasesApiType[]; } export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - }; + /** + * An account or database connection string + */ + connectionString?: string; + + postgresData?: { + hostName: string; + port: string; + databaseName: string | undefined; + username: string | undefined; + password: string | undefined; + } } diff --git a/Source/vscode-cosmosdbgraph.api.d.ts b/Source/vscode-cosmosdbgraph.api.d.ts index bf8d4c769..95cde2531 100644 --- a/Source/vscode-cosmosdbgraph.api.d.ts +++ b/Source/vscode-cosmosdbgraph.api.d.ts @@ -4,26 +4,26 @@ *--------------------------------------------------------------------------------------------*/ export interface CosmosDBGraphExtensionApi { - apiVersion: string; + apiVersion: string; - openGraphExplorer(config: IGraphConfiguration): Promise; + openGraphExplorer(config: IGraphConfiguration): Promise; } export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; + host: string; + port: number; + ssl: boolean; } export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; + // e.g. https://graphaccount.documents.azure.com:443 + documentEndpoint: string; - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; + gremlinEndpoint?: IGremlinEndpoint; + possibleGremlinEndpoints: IGremlinEndpoint[]; - key: string; - databaseName: string; - graphName: string; - tabTitle: string; + key: string; + databaseName: string; + graphName: string; + tabTitle: string; } diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e16bd2f53..000000000 --- a/package-lock.json +++ /dev/null @@ -1,21347 +0,0 @@ -{ - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "license": "SEE LICENSE IN LICENSE.md", - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "engines": { - "vscode": "^1.66.0" - } - }, - "node_modules/@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@azure/abort-controller/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "node_modules/@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-cosmosdb/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-postgresql-flexible/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-postgresql/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-resources-subscriptions/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/arm-storage-profile-2020-09-01-hybrid/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/arm-storage/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-auth/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-client/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-lro/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "dependencies": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-paging/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-tracing/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/core-util/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "dependencies": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/cosmos/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/cosmos/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@azure/logger/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "node_modules/@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "dependencies": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - } - }, - "node_modules/@azure/ms-rest-js/node_modules/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, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "dependencies": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "dependencies": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "dependencies": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - }, - "peerDependencies": { - "tslib": "*" - } - }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "node_modules/@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "dependencies": { - "@typescript-eslint/parser": "^4.28.5" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=4", - "eslint": ">=7", - "eslint-plugin-import": ">=2" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "dependencies": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@microsoft/vscode-azext-azureutils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "dependencies": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "bin": { - "vscode-sort-package-json": "scripts/sortPackageJson.mjs" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "dev": true - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@microsoft/vscode-azext-dev/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "dependencies": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@microsoft/vscode-azext-utils/node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - }, - "node_modules/@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "peerDependencies": { - "@azure/ms-rest-azure-env": "^2.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "dependencies": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "node_modules/@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "dependencies": { - "@types/webpack": "*" - } - }, - "node_modules/@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "node_modules/@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "dependencies": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "node_modules/@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "dependencies": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - } - }, - "node_modules/@types/gulp/node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/gulp/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@types/gulp/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@types/gulp/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/gulp/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/gulp/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/@types/gulp/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/@types/gulp/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "node_modules/@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "dependencies": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "node_modules/@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "node_modules/@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "node_modules/@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/uglify-js/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "node_modules/@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "node_modules/@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "dependencies": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "node_modules/@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "node_modules/@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "dependencies": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/webpack/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "dependencies": { - "fast-memoize": "^2.3.2" - } - }, - "node_modules/@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "dependencies": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - }, - "engines": { - "vscode": "^1.60.0" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/@vscode/test-electron/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "engines": { - "node": ">= 0.6.15" - } - }, - "node_modules/adal-node/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "node_modules/antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true, - "bin": { - "antlr4ts": "antlr4ts" - } - }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "dependencies": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - }, - "engines": { - "node": ">=8.9.0" - }, - "peerDependencies": { - "webpack": "*" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "node_modules/copy-props/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "dependencies": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/copy-webpack-plugin/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/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, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/copy-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true, - "engines": { - "node": ">0.4.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-compare/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "dev": true - }, - "node_modules/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 - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/enquirer/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/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 - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-glob/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-glob/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "dev": true, - "dependencies": { - "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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-cli/node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, - "engines": { - "node": ">=10.23.2" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "dependencies": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/indexable-array/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/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 - }, - "node_modules/log-symbols/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true, - "engines": { - "node": ">= 6.14.4" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "peerDependencies": { - "mocha": ">=2.2.5" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-junit-reporter/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha-junit-reporter/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha-junit-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - } - }, - "node_modules/mocha-multi-reporters/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/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 - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - }, - "peerDependenciesMeta": { - "aws4": { - "optional": true - }, - "bson-ext": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "mongodb-extjson": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "dependencies": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/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, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "dependencies": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dependencies": { - "split": "^1.0.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "dependencies": { - "parseley": "^0.7.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, - "node_modules/semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/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 - }, - "node_modules/slice-ansi/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-color/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/table/node_modules/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/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, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/tas-client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tmp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "dependencies": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "engines": { - "node": ">=6.11.5" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/ts-loader/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "out/vsce" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "dependencies": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - } - }, - "node_modules/vscode-json-languageservice/node_modules/vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "dependencies": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "engines": { - "vscode": "^1.41.0" - } - }, - "node_modules/vscode-languageclient/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "dependencies": { - "vscode-languageserver-protocol": "^3.15.3" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "dependencies": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "node_modules/vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "dependencies": { - "tas-client": "0.1.45" - }, - "engines": { - "vscode": "^1.19.1" - } - }, - "node_modules/vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-cli/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/webpack-cli/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-cli/node_modules/rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, - "node_modules/yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@azure/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==", - "requires": { - "tslib": "^2.0.0" - }, - "dependencies": { - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - } - } - }, - "@azure/arm-cosmosdb": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-cosmosdb/-/arm-cosmosdb-15.0.0.tgz", - "integrity": "sha512-F0lrY+11XRBwMZgXUkGMh8EaSmeHCWjRgblRp+PKlce3UUmC4lgbrZYrJdhE2rxDkOS4sz+zL1lnN2qMuejSNg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql/-/arm-postgresql-6.0.0.tgz", - "integrity": "sha512-7t9kVbUzfmd4OpbfPuZOYn6Gh/LatBg3EdHGM33vBJ6wl7bFZHMHyyF9K2rjnVnCotdqXxtByo2s5txUAgkUiA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-postgresql-flexible": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-postgresql-flexible/-/arm-postgresql-flexible-5.0.0.tgz", - "integrity": "sha512-j21UhvmLkNKm3FcJs5YTgc3GfDA6ZtFl9Sp7+uuQN+7ea05nBVwXjuMpVAU50dLho+Aab+r+XI1Ie8p2Onod0g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/arm-resources": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.0.0.tgz", - "integrity": "sha512-Dd2tsKnTJ62D/LYsr2njnj+/1HsUclJwBGZ+tVVfmdQir9pnGA11k2jhsuhHiCRU0auEKgMDNfhip7q/TpSrXQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/arm-resources-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-5n+W6rdh1z49VMfBRWN7cDfinMxpg4AI7gP/gpcivGFoFC2a64YpQOv/ev4iKPwq4Pc1Ji1pJ5/l6RgtXtss5g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-resources-subscriptions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-2.0.1.tgz", - "integrity": "sha512-K/WTPFQz12eTdpR/VgB56R0qQ/MFJmsYuBAw5k/hLmMAZNIqBTy96YMRPzFLjpDZRs/HpLV61vpUGldBQL9iUw==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-storage": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.2.0.tgz", - "integrity": "sha512-jLUsAVFq5YBOYQfhE6L+KaUs+lntctKVafPz50FFScfzPMHYT/SptQGZ7BKzAJBBE/evdt8afmt2NSdl8Szomg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.3", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/arm-storage-profile-2020-09-01-hybrid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-2.0.0.tgz", - "integrity": "sha512-qBO9jHugUY7U3dDjokFJ6v3mQdQlFZeY2OHuihHy5Q8d0Fkdv4kO+6nbKXevcOVWlGS1E4Kd1Ah+yqv9YItGWA==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/arm-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-2.0.0.tgz", - "integrity": "sha512-+ys2glK5YgwZ9KhwWblfAQIPABtiB5OdKEpPOpcvr7B5ygYTwZuSUNObX9MRu/MyiRo1zDlUvlxHltBphq/bLQ==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-js": "^2.0.1", - "@azure/ms-rest-js": "^2.0.4", - "tslib": "^1.10.0" - } - }, - "@azure/core-asynciterator-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz", - "integrity": "sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw==" - }, - "@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-paging": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.1.tgz", - "integrity": "sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA==", - "requires": { - "@azure/core-asynciterator-polyfill": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - } - } - }, - "@azure/core-util": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", - "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - } - } - }, - "@azure/cosmos": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.15.1.tgz", - "integrity": "sha512-Pjn9CcoipUSsm/r9ZqAeyrqIQnh0AOeIDwYs/3pcLumK9ezCVFrfeLoOfas4Dm2X8bwL+/9puKAM55LJEaQwWg==", - "requires": { - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "debug": "^4.1.1", - "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } - } - }, - "@azure/ms-rest-azure-env": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", - "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" - }, - "@azure/ms-rest-azure-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz", - "integrity": "sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@azure/ms-rest-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.7.0.tgz", - "integrity": "sha512-ngbzWbqF+NmztDOpLBVDxYM+XLcUj7nKhxGbSU9WtIsXfRB//cf2ZbAG5HkOrhU9/wd/ORRB6lM/d69RKVjiyA==", - "dev": true, - "requires": { - "@azure/core-auth": "^1.1.4", - "abort-controller": "^3.0.0", - "form-data": "^2.5.0", - "node-fetch": "^2.6.7", - "tslib": "^1.10.0", - "tunnel": "0.0.6", - "uuid": "^8.3.2", - "xml2js": "^0.5.0" - }, - "dependencies": { - "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 - } - } - }, - "@azure/ms-rest-nodeauth": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.1.tgz", - "integrity": "sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==", - "dev": true, - "requires": { - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.2.2" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@microsoft/1ds-core-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz", - "integrity": "sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==", - "requires": { - "@microsoft/applicationinsights-core-js": "2.8.4", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/1ds-post-js": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz", - "integrity": "sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==", - "requires": { - "@microsoft/1ds-core-js": "3.2.3", - "@microsoft/applicationinsights-shims": "^2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-core-js": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz", - "integrity": "sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==", - "requires": { - "@microsoft/applicationinsights-shims": "2.0.1", - "@microsoft/dynamicproto-js": "^1.1.6" - } - }, - "@microsoft/applicationinsights-shims": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz", - "integrity": "sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==" - }, - "@microsoft/dynamicproto-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz", - "integrity": "sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==" - }, - "@microsoft/eslint-config-azuretools": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-config-azuretools/-/eslint-config-azuretools-0.1.0.tgz", - "integrity": "sha512-1H95Y6RzUxl96BHneJeLdf2zsJFTZA1Ho6O6lAhky/mfYRulXFOGzeWyffwNScWdWFkHxGSmec5XnkQhoHKy5A==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^4.28.5" - } - }, - "@microsoft/vscode-azext-azureutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-2.0.2.tgz", - "integrity": "sha512-r+7NqedkvfFazztO7kxT1AU/B/UfiGhTDlRtFHx+W5bhp+yJw0eOtX8VPJXXSXoOaq2dzuGBwxAQ0bDD1lNPcQ==", - "requires": { - "@azure/arm-resources": "^5.0.0", - "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/arm-resources-subscriptions": "^2.0.0", - "@azure/arm-storage": "^18.0.0", - "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0", - "@azure/core-client": "^1.6.0", - "@azure/core-rest-pipeline": "^1.9.0", - "@azure/logger": "^1.0.4", - "@microsoft/vscode-azext-utils": "^2.0.0", - "semver": "^7.3.7", - "uuid": "^9.0.0" - }, - "dependencies": { - "@azure/arm-resources": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz", - "integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@microsoft/vscode-azext-dev": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-dev/-/vscode-azext-dev-0.1.4.tgz", - "integrity": "sha512-IDNDTpLRCTK1uIBmfG1Q7Ut1gMKSnkj3oFMvHzD4WhdFLdifxtzR4fBdStX5XlZEyXnCTn+SMyTaM8XKuQvw6Q==", - "dev": true, - "requires": { - "@azure/arm-subscriptions": "^2.0.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-js": "^2.2.1", - "@azure/ms-rest-nodeauth": "^3.0.5", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.0", - "fs-extra": "^8.0.0", - "terser-webpack-plugin": "^5.0.0", - "ts-loader": "^5.3.3", - "webpack": "5.28.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", - "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "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 - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz", - "integrity": "sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.46", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.7.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "^5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.0.0", - "webpack-sources": "^2.1.1" - } - }, - "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } - } - } - }, - "@microsoft/vscode-azext-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-2.1.0.tgz", - "integrity": "sha512-nkV5RODko5/XOBeh6kTkiMqkls+mB7kcLKKqwZPSdZijouCSawzPpurNf5erc9hqt0q9oCl5cRx1UwDXFw9tVQ==", - "requires": { - "@microsoft/vscode-azureresources-api": "^2.0.4", - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "semver": "^7.3.7", - "uuid": "^9.0.0", - "vscode-tas-client": "^0.1.47", - "vscode-uri": "^3.0.6" - }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" - } - } - }, - "@microsoft/vscode-azureresources-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-2.1.0.tgz", - "integrity": "sha512-dqjLyHl0OJgnjEtMtZEDvA9YovszWnE2k3ktEcHiTHWZ62luYrhOQhMzJjGArSFH3ANRCWgS6A1q4OTjZoBrKQ==", - "requires": {} - }, - "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - } - }, - "@npmcli/move-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz", - "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "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" - } - } - } - }, - "@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "requires": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", - "dev": true - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.2.tgz", - "integrity": "sha512-+uWmsejEHfmSjyyM/LkrP0orfE2m5Mx9Xel4tXNeqi1ldK5XMQcDsFkBmLDtuyKUbxj2jGDo0H240fbCRJZo7Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/copy-webpack-plugin": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.4.0.tgz", - "integrity": "sha512-f5mQG5c7xH3zLGrEmKgzLLFSGNB7Y4+4a+a1X4DvjgfbTEWEZUNNXUqGs5tBVCtb5qKPzm2z+6ixX3xirWmOCg==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, - "@types/documentdb": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz", - "integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/glob-stream": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.1.tgz", - "integrity": "sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/gulp": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.9.tgz", - "integrity": "sha512-zzT+wfQ8uwoXjDhRK9Zkmmk09/fbLLmN/yDHFizJiEKIve85qutOnXcP/TM2sKPBTU+Jc16vfPbOMkORMUBN7Q==", - "dev": true, - "requires": { - "@types/undertaker": "*", - "@types/vinyl-fs": "*", - "chokidar": "^3.3.1" - }, - "dependencies": { - "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" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "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" - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.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" - } - }, - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "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" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", - "dev": true - }, - "@types/mongodb": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.4.tgz", - "integrity": "sha512-1Q781+rC+hYB34Ped9dRLOWsw1yTNwqphqkRyJR/yFuoWoZ3664s6RxilVSkqEm3lwFmpTYCXtGudxSpHHGDIQ==", - "dev": true, - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", - "dev": true - }, - "@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true - } - } - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/tapable": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", - "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.12.0.tgz", - "integrity": "sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "@types/undertaker": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.7.tgz", - "integrity": "sha512-xuY7nBwo1zSRoY2aitp/HArHfTulFAKql2Fr4b4mWbBBP+F50n7Jm6nwISTTMaDk2xvl92O10TTejVF0Q9mInw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/undertaker-registry": "*", - "async-done": "~1.3.2" - } - }, - "@types/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==", - "dev": true - }, - "@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/vinyl-fs": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.12.tgz", - "integrity": "sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==", - "dev": true, - "requires": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/vscode": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz", - "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==", - "dev": true - }, - "@types/webpack": { - "version": "4.41.26", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", - "integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==", - "dev": true, - "requires": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", - "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", - "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", - "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.29.1", - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/typescript-estree": "4.29.1", - "debug": "^4.3.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", - "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1" - } - }, - "@typescript-eslint/types": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", - "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", - "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "@typescript-eslint/visitor-keys": "4.29.1", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", - "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.1", - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", - "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" - } - }, - "@typescript-eslint/types": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", - "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", - "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.31.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", - "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.31.2", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@typescript-plus/fast-memoize-decorator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@typescript-plus/fast-memoize-decorator/-/fast-memoize-decorator-0.1.0.tgz", - "integrity": "sha512-OViz04jbmg7yyPso2rgrn/hEuXeELU2yHkBpdultWyvbyRRHrkK9ZD+i9jYbVgJGE6gJ5iz7HYOXZ2ORHbqlpw==", - "requires": { - "fast-memoize": "^2.3.2" - } - }, - "@vscode/extension-telemetry": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz", - "integrity": "sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==", - "requires": { - "@microsoft/1ds-core-js": "^3.2.3", - "@microsoft/1ds-post-js": "^3.2.3" - } - }, - "@vscode/test-electron": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.0.tgz", - "integrity": "sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "dependencies": { - "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" - } - } - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", - "dev": true, - "requires": {} - }, - "@xmldom/xmldom": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz", - "integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "requires": {} - }, - "adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.7.0", - "async": "^2.6.3", - "axios": "^0.21.1", - "date-utils": "*", - "jws": "3.x.x", - "underscore": ">= 1.3.1", - "uuid": "^3.1.0", - "xpath.js": "~1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "antlr4ts": { - "version": "0.4.1-alpha.0", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.4.1-alpha.0.tgz", - "integrity": "sha1-rFcX8w8++jYXsATo/0+GC5x9TSA=" - }, - "antlr4ts-cli": { - "version": "0.4.0-canary.37504efa", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.4.0-canary.37504efa.tgz", - "integrity": "sha512-Z97vuqOzUmuHq+6pDU3bKIL6LYvs4uWs0eBWi3Ju/mt2UzKQRqchxalRgceJR6RtPieARxWJoBhCU2kOGmiJ2Q==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - } - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001246", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001246.tgz", - "integrity": "sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "requires": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - } - } - }, - "copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", - "dev": true, - "requires": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "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" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.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" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", - "dev": true - }, - "dayjs": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", - "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.3.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.783.tgz", - "integrity": "sha512-296P577qmXQHgLa3zAYdB9zOhqzt7lckmbLAJO78lIXGBhYA5NVI2WRwyYJPZ614eJxd0Bew7RA72vFOFXyogA==", - "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 - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "envinfo": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", - "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "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==" - }, - "eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.21", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "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 - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "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" - } - }, - "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" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "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 - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.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" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.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" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "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" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "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" - } - } - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "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" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-to-text": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.0.tgz", - "integrity": "sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", - "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", - "dev": true - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "indexable-array": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/indexable-array/-/indexable-array-0.7.0.tgz", - "integrity": "sha512-uHpBgsGbXSIkM5aA/RR5FKc2TMJ0lLRLz+pepiRrUVbNb8vB+9lBiRQyVNF+Houfcl5H4XZK50tUdlHHRrZpiA==", - "requires": { - "lodash.set": "^4.3.2", - "sorted-array-functions": "^1.2.0", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", - "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.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": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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" - } - } - } - }, - "loglevelnext": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-3.0.1.tgz", - "integrity": "sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "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.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^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" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.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 - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "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" - } - }, - "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 - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "mocha-junit-reporter": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz", - "integrity": "sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "md5": "^2.1.0", - "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", - "xml": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.16.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongodb-extended-json": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.11.0.tgz", - "integrity": "sha512-+PLUMH7amvTYumCUR6alR474KmqtlmYeceJjsC+zcfdXls9IotfTp2WIuD6X5tO9dLDVCDqboqjgvXj/JjGj6g==", - "requires": { - "async": "^3.1.0", - "bson": "^1.0.1", - "event-stream": "^4.0.1", - "JSONStream": "^1.1.1", - "lodash.isfunction": "^3.0.6", - "lodash.transform": "^4.6.0", - "moment": "^2.10.6", - "raf": "^3.1.0" - } - }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "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 - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "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" - } - } - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "requires": { - "require-at": "^1.0.6" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "requires": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "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 - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.2.tgz", - "integrity": "sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-structure": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.15.0.tgz", - "integrity": "sha512-BBnuKV2gGZHs+2lFi4LY4fwX5sTGvMHCBk9m5klUy7zT1vGP3iK1XRXWwacgmvjynY9Lz3u224eCW5Ho9amKGQ==", - "requires": { - "@typescript-plus/fast-memoize-decorator": "^0.1.0", - "dotenv": "^8.2.0", - "fast-memoize": "^2.5.2", - "indexable-array": "^0.7.0", - "inflection": "^1.12.0", - "json5": "^2.1.3", - "lodash.get": "^4.4.2", - "pg": "^8.0.3", - "pg-connection-string": "^2.2.1" - } - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "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" - }, - "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" - } - }, - "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 - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.6.tgz", - "integrity": "sha512-o2a4gxeFcox+CgB3Ig/kNHBP23PiEXHCXx7pcIIsvzoNz4qv+lKTyiSkjOXIMNUl12MO/mOYl2K6wR9X5K6Plg==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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 - } - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "requires": { - "parseley": "^0.7.0" - } - }, - "semaphore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.0.5.tgz", - "integrity": "sha1-tJJXbmavGT25XWXiXsU/Xxl5jWA=" - }, - "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "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 - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.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" - } - }, - "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 - }, - "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 - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.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" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "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" - } - } - } - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "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 - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "table": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.2.tgz", - "integrity": "sha512-I9/Ca6Huf2oxFag7crD0DhA+arIdfLtWunSn0NIXSzjtUlDgIBGVZY7SsMkNPNT3Psd/z4gza0nuEpmra9eRbg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "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 - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "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" - } - } - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", - "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } - } - }, - "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "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" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - } - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typed-rest-client": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz", - "integrity": "sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vsce": { - "version": "1.96.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.96.1.tgz", - "integrity": "sha512-KnEVqjfc1dXrpZsbJ8J7B9VQ7GAAx8o5RqBNk42Srv1KF9+e2/aXchQHe9QZxeUs/FiliHoMGpGvnHTXwKIT2A==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "vscode-json-languageservice": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz", - "integrity": "sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==", - "requires": { - "jsonc-parser": "^2.2.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-nls": "^4.1.1", - "vscode-uri": "^2.1.1" - }, - "dependencies": { - "vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" - } - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz", - "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.3" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "vscode-languageserver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz", - "integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==", - "requires": { - "vscode-languageserver-protocol": "^3.15.3" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" - }, - "vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", - "requires": { - "tas-client": "0.1.45" - } - }, - "vscode-uri": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", - "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==" - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.76.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", - "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - } - } - }, - "webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "enquirer": "^2.3.6", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - } - } - }, - "webpack-log": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-3.0.2.tgz", - "integrity": "sha512-ijm2zgqTY2omtlxRNrtDqxAQOrfAGMxWg9fQB/kuFSeZjx/OkYnfYLqsjf/JkrWOHINMzqxaJDXaog6Mx9KaHg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "loglevelnext": "^3.0.1", - "nanoid": "^2.0.3" - } - }, - "webpack-merge": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", - "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "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" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xpath.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", - "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index 4b494c176..48ee67fc3 100644 --- a/package.json +++ b/package.json @@ -1,1114 +1,1112 @@ { - "name": "vscode-cosmosdb", - "version": "0.20.1-alpha", - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", - "publisher": "ms-azuretools", - "displayName": "Azure Databases", - "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "engines": { - "vscode": "^1.66.0" - }, - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "icon": "resources/databases.png", - "categories": [ - "Azure" - ], - "keywords": [ - "Cosmos DB", - "DocumentDB", - "Graph", - "Gremlin", - "MongoDB", - "PostgreSQL" - ], - "preview": true, - "homepage": "https://github.com/microsoft/vscode-cosmosdb/blob/main/README.md", - "bugs": { - "url": "https://github.com/microsoft/vscode-cosmosdb/issues" - }, - "license": "SEE LICENSE IN LICENSE.md", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-cosmosdb" - }, - "main": "./main", - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], - "contributes": { - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - }, - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } + "name": "vscode-cosmosdb", + "version": "0.0.1", + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", + "publisher": "playform", + "displayName": "Azure Databases", + "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "icon": "resources/databases.png", + "preview": true, + "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", + "bugs": { + "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" + }, + "main": "./main", + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "contributes": { + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" + }, + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } ], - "commands": [ - { - "category": "Azure Databases", - "command": "azureDatabases.createServer", - "title": "Create Server...", - "icon": "$(add)" - }, - { - "category": "Cosmos DB", - "command": "azureDatabases.detachDatabaseAccount", - "title": "Detach" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.loadMore", - "title": "Load More" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.refresh", - "title": "Refresh", - "icon": "$(refresh)" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.reportIssue", - "title": "Report Issue..." - }, - { - "category": "Azure Databases", - "command": "azureDatabases.update", - "title": "Update to Cloud", - "icon": "$(cloud-upload)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachDatabaseAccount", - "title": "Attach Database Account...", - "icon": "$(plug)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachEmulator", - "title": "Attach Emulator..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.connectMongoDB", - "title": "Connect to Database..." - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBCollection", - "title": "Create Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDatabase", - "title": "Create Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDocument", - "title": "Create Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBStoredProcedure", - "title": "Create Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraph", - "title": "Create Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraphDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoCollection", - "title": "Create Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDocument", - "title": "Create Document" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.deleteAccount", - "title": "Delete Account..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBCollection", - "title": "Delete Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDatabase", - "title": "Delete Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDocument", - "title": "Delete Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraph", - "title": "Delete Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraphDatabase", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoCollection", - "title": "Delete Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDB", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDocument", - "title": "Delete Document..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeAllMongoCommands", - "title": "Execute All MongoDB Commands" - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeMongoCommand", - "title": "Execute MongoDB Command" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.importDocument", - "title": "Import Document into a Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.launchMongoShell", - "title": "Launch Shell" - }, - { - "category": "MongoDB", - "command": "cosmosDB.newMongoScrapbook", - "title": "New Mongo Scrapbook", - "icon": "$(new-file)" - }, - { - "category": "MongoDB", - "command": "cosmosDB.openCollection", - "title": "Open Collection" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openDocument", - "title": "Open Document" - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.openGraphExplorer", - "title": "Open Graph Explorer" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.configureFirewall", - "title": "Configure Firewall" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.connectDatabase", - "title": "Connect to Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createDatabase", - "title": "Create Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createFunctionQuery", - "title": "Create Function Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createStoredProcedureQuery", - "title": "Create Stored Procedure Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteDatabase", - "title": "Delete Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteFunction", - "title": "Delete Function..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteServer", - "title": "Delete Server..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteTable", - "title": "Delete Table..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.enterCredentials", - "title": "Enter Server Credentials" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.executeQuery", - "title": "Execute Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openFunction", - "title": "Open Function" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.showPasswordlessWiki", - "title": "Learn more about authenticating with Azure Active Directory", - "icon": "$(warning)" - } + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." + } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] + } + }, + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" ], - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } + "extensions": [ + ".mongo" ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId==postgres" - } - ], - "editor/title": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "azureDatabases.createServer", - "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", - "group": "1@1" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteServer", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@1" - }, - { - "command": "postgreSQL.showPasswordlessWiki", - "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", - "group": "inline" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@1" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@2" - }, - { - "command": "cosmosDB.connectMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "2@1" - }, - { - "command": "cosmosDB.deleteMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@4" - }, - { - "command": "cosmosDB.deleteMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraphDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteTable", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteFunction", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", - "group": "1@2" - }, - { - "command": "cosmosDB.attachDatabaseAccount", - "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "1@1" - }, - { - "command": "cosmosDB.attachEmulator", - "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", - "group": "1@2" - }, - { - "command": "cosmosDB.openCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "2@1" - }, - { - "command": "postgreSQL.copyConnectionString", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "2@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", - "group": "1@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "2@1" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@3" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@1" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createFunctionQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "1@1" - }, - { - "command": "postgreSQL.createStoredProcedureQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "1@1" - } - ], - "explorer/context": [ - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId == json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId == postgres" - } - ], - "commandPalette": [ - { - "command": "azureDatabases.loadMore", - "when": "never" - }, - { - "command": "azureDatabases.refresh", - "when": "never" - }, - { - "command": "azureDatabases.update", - "when": "never" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "editorLangId == 'mongo'" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "editorLangId == 'mongo'" - }, - { - "command": "postgreSQL.executeQuery", - "when": "editorLangId == 'postgres'" - } - ] - }, - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" - } + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" - } - } + "extensions": [ + ".psql" + ] + } + ], + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "commands": [ + { + "category": "Azure Databases", + "command": "azureDatabases.createServer", + "title": "Create Server...", + "icon": "$(add)" + }, + { + "category": "Cosmos DB", + "command": "azureDatabases.detachDatabaseAccount", + "title": "Detach" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.loadMore", + "title": "Load More" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.reportIssue", + "title": "Report Issue..." + }, + { + "category": "Azure Databases", + "command": "azureDatabases.update", + "title": "Update to Cloud", + "icon": "$(cloud-upload)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachDatabaseAccount", + "title": "Attach Database Account...", + "icon": "$(plug)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachEmulator", + "title": "Attach Emulator..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.connectMongoDB", + "title": "Connect to Database..." + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBCollection", + "title": "Create Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDatabase", + "title": "Create Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDocument", + "title": "Create Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBStoredProcedure", + "title": "Create Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraph", + "title": "Create Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraphDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoCollection", + "title": "Create Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDocument", + "title": "Create Document" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.deleteAccount", + "title": "Delete Account..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBCollection", + "title": "Delete Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDatabase", + "title": "Delete Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDocument", + "title": "Delete Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraph", + "title": "Delete Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraphDatabase", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoCollection", + "title": "Delete Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDB", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDocument", + "title": "Delete Document..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeAllMongoCommands", + "title": "Execute All MongoDB Commands" + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeMongoCommand", + "title": "Execute MongoDB Command" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.importDocument", + "title": "Import Document into a Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.launchMongoShell", + "title": "Launch Shell" + }, + { + "category": "MongoDB", + "command": "cosmosDB.newMongoScrapbook", + "title": "New Mongo Scrapbook", + "icon": "$(new-file)" + }, + { + "category": "MongoDB", + "command": "cosmosDB.openCollection", + "title": "Open Collection" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openDocument", + "title": "Open Document" + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.openGraphExplorer", + "title": "Open Graph Explorer" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.configureFirewall", + "title": "Configure Firewall" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.connectDatabase", + "title": "Connect to Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createDatabase", + "title": "Create Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createFunctionQuery", + "title": "Create Function Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createStoredProcedureQuery", + "title": "Create Stored Procedure Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteDatabase", + "title": "Delete Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteFunction", + "title": "Delete Function..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteServer", + "title": "Delete Server..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteTable", + "title": "Delete Table..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.enterCredentials", + "title": "Enter Server Credentials" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.executeQuery", + "title": "Execute Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openFunction", + "title": "Open Function" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.showPasswordlessWiki", + "title": "Learn more about authenticating with Azure Active Directory", + "icon": "$(warning)" + } + ], + "submenus": [ + { + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId==postgres" + } + ], + "editor/title": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "azureDatabases.createServer", + "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", + "group": "1@1" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteServer", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@1" + }, + { + "command": "postgreSQL.showPasswordlessWiki", + "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", + "group": "inline" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@1" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@2" + }, + { + "command": "cosmosDB.connectMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "2@1" + }, + { + "command": "cosmosDB.deleteMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@4" + }, + { + "command": "cosmosDB.deleteMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraphDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteTable", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteFunction", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", + "group": "1@2" + }, + { + "command": "cosmosDB.attachDatabaseAccount", + "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "1@1" + }, + { + "command": "cosmosDB.attachEmulator", + "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", + "group": "1@2" + }, + { + "command": "cosmosDB.openCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "2@1" + }, + { + "command": "postgreSQL.copyConnectionString", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "2@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", + "group": "1@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "2@1" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@3" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@1" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createFunctionQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "1@1" + }, + { + "command": "postgreSQL.createStoredProcedureQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "1@1" + } + ], + "explorer/context": [ + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId == json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId == postgres" + } + ], + "commandPalette": [ + { + "command": "azureDatabases.loadMore", + "when": "never" + }, + { + "command": "azureDatabases.refresh", + "when": "never" + }, + { + "command": "azureDatabases.update", + "when": "never" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "editorLangId == 'mongo'" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "editorLangId == 'mongo'" + }, + { + "command": "postgreSQL.executeQuery", + "when": "editorLangId == 'postgres'" + } + ] }, - "scripts": { - "vscode:prepublish": "npm run webpack-prod", - "build": "tsc", - "cleanReadme": "gulp cleanReadme", - "clean": "git clean -dfx", - "compile": "tsc -watch", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", - "all": "npm i && npm run lint && npm test", - "prepare": "husky install" - }, - "devDependencies": { - "@azure/arm-resources": "^4.0.0", - "@microsoft/eslint-config-azuretools": "^0.1.0", - "@microsoft/vscode-azext-dev": "^0.1.4", - "@types/copy-webpack-plugin": "^6.4.0", - "@types/documentdb": "^1.10.2", - "@types/fs-extra": "^8.1.0", - "@types/gulp": "^4.0.6", - "@types/mocha": "^7.0.2", - "@types/mongodb": "^3.3.2", - "@types/node": "^14.0.0", - "@types/pg": "^8.10.2", - "@types/vscode": "1.66.0", - "@typescript-eslint/eslint-plugin": "^4.31.1", - "@vscode/test-electron": "^2.1.5", - "antlr4ts-cli": "^0.4.0-alpha.4", - "copy-webpack-plugin": "^6.4.0", - "eslint": "^7.19.0", - "eslint-plugin-import": "^2.22.1", - "glob": "^7.1.6", - "gulp": "^4.0.0", - "husky": "^7.0.2", - "mocha": "^10.2.0", - "mocha-junit-reporter": "^1.18.0", - "mocha-multi-reporters": "^1.1.7", - "ts-node": "^7.0.1", - "typescript": "^4.4.3", - "vsce": "^1.87.0", - "webpack": "^5.76.0", - "webpack-cli": "^4.6.0", - "webpack-log": "^3.0.2" - }, - "dependencies": { - "@azure/arm-cosmosdb": "^15.0.0", - "@azure/arm-postgresql": "^6.0.0", - "@azure/arm-postgresql-flexible": "^5.0.0", - "@azure/cosmos": "^3.6.3", - "@microsoft/vscode-azext-azureutils": "^2.0.2", - "@microsoft/vscode-azext-utils": "^2.1.0", - "antlr4ts": "^0.4.1-alpha.0", - "bson": "^1.1.3", - "fs-extra": "^8.0.0", - "mongodb": "^3.6.10", - "mongodb-extended-json": "^1.10.0", - "open": "^8.0.0", - "pg": "^8.11.2", - "pg-connection-string": "^2.6.2", - "pg-structure": "^7.15.0", - "semver": "^7.5.2", - "underscore": "^1.12.1", - "vscode-json-languageservice": "^3.0.8", - "vscode-languageclient": "^6.1.3", - "vscode-languageserver": "^6.1.1", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.1" - }, - "extensionDependencies": [ - "ms-azuretools.vscode-azureresourcegroups" - ] + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null + }, + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] + }, + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 + }, + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" + }, + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" + }, + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + } + }, + "scripts": { + "vscode:prepublish": "npm run webpack-prod", + "build": "tsc", + "cleanReadme": "gulp cleanReadme", + "clean": "git clean -dfx", + "compile": "tsc -watch", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", + "all": "npm i && npm run lint && npm test", + "prepare": "husky install", + "prepublishOnly": "TypeScriptESBuild 'Source/**/*.ts'" + }, + "devDependencies": { + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.2", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.13", + "@types/fs-extra": "11.0.4", + "@types/gulp": "4.0.17", + "@types/mocha": "10.0.6", + "@types/mongodb": "4.0.6", + "@types/node": "20.9.4", + "@types/pg": "8.10.9", + "@types/vscode": "1.84.2", + "@typescript-eslint/eslint-plugin": "6.12.0", + "@vscode/test-electron": "2.3.6", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.54.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.3.2", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2", + "typescript-esbuild": "0.3.1" + }, + "dependencies": { + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.3.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" + }, + "extensionDependencies": [ + "ms-azuretools.vscode-azureresourcegroups" + ], + "type": "module", + "private": "false", + "publishConfig": { + "access": "public" + }, + "author": { + "name": "Nikola Hristov", + "email": "nikola@nikolahristov.tech", + "url": "https://nikolahristov.tech" + } } diff --git a/src/AzureDBExperiences.ts b/src/AzureDBExperiences.ts deleted file mode 100644 index be9765dc6..000000000 --- a/src/AzureDBExperiences.ts +++ /dev/null @@ -1,118 +0,0 @@ -/* ------------------------------------------------------------------------------------------ - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { nonNullProp } from './utils/nonNull'; - -export enum API { - MongoDB = 'MongoDB', - Graph = 'Graph', - Table = 'Table', - Core = 'Core', - PostgresSingle = 'PostgresSingle', - PostgresFlexible = 'PostgresFlexible' -} - -export enum DBAccountKind { - MongoDB = 'MongoDB', - GlobalDocumentDB = 'GlobalDocumentDB' -} - -export type CapabilityName = 'EnableGremlin' | 'EnableTable'; - -export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; - } - return info; -} - -export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { - - const experience: Experience | undefined = tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); - const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); - return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); - -} - -export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { - return GremlinExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; -} - -export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; - - longName: string; - shortName: string; - description?: string; - - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; - - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; -} - -export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } -} - -export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } -} - -export function getExperienceQuickPick(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; -} - -export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; -} - -// Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" -// Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; -export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; -export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; -export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; -const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; -const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; - -const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; -const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; -const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); diff --git a/src/DatabasesFileSystem.ts b/src/DatabasesFileSystem.ts deleted file mode 100644 index 93c2b4938..000000000 --- a/src/DatabasesFileSystem.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; -import { FileChangeType } from "vscode-languageclient"; -import { ext } from "./extensionVariables"; -import { localize } from "./utils/localize"; -import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; -import { getNodeEditorLabel } from "./utils/vscodeUtils"; - -export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; -} - -export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = 'azureDatabases'; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; - - public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { - const size: number = Buffer.byteLength(await node.getFileContent(context)); - return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; - } - - public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { - return Buffer.from(await node.getFileContent(context)); - } - - public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { - const showSavePromptKey: string = 'showSavePrompt'; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = 'cosmosDB'; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { - const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); - const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError('dontUpload'); - } - } - - await node.writeFileContent(context, content.toString()); - await node.refresh(context); - - const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); - ext.outputChannel.appendLog(updatedMessage); - } - - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } - - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } - - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } -} diff --git a/src/ParsedConnectionString.ts b/src/ParsedConnectionString.ts deleted file mode 100644 index 99654ef5a..000000000 --- a/src/ParsedConnectionString.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; - - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; - - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } - - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } - - public get fullId(): string { - return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; - } -} diff --git a/src/azureAccountUtils.ts b/src/azureAccountUtils.ts deleted file mode 100644 index 7f37da4cd..000000000 --- a/src/azureAccountUtils.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtServiceClientCredentials } from "@microsoft/vscode-azext-utils"; -import { getApiExport } from "./getExtensionApi"; - -const azureAccountExtensionId = "ms-vscode.azure-account"; - -type AzureSession = { - userId: string; -}; - -/** - * @returns The user session of the signed-in azure account. - */ -export async function getAzureAdUserSession(): Promise { - const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; -} - -/** - * Gets a function that can request an access token for a specified scope for the signed-in azure account. - */ -export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { - return async () => { - const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; - return getTokenResult?.token ?? ""; - }; -} diff --git a/src/commands/api/DatabaseAccountTreeItemInternal.ts b/src/commands/api/DatabaseAccountTreeItemInternal.ts deleted file mode 100644 index 89a8c1164..000000000 --- a/src/commands/api/DatabaseAccountTreeItemInternal.ts +++ /dev/null @@ -1,106 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { API } from '../../AzureDBExperiences'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; - -export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { - protected _parsedCS: ParsedConnectionString; - private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; - - constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } - - public get connectionString(): string { - return this._parsedCS.connectionString; - } - - public get hostName(): string { - return this._parsedCS.hostName; - } - - public get port(): string { - return this._parsedCS.port; - } - - public get azureData(): { accountName: string, accountId: string } | undefined { - if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), - accountId: this._accountNode.fullId - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId - }; - } - } - return undefined; - } - - public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey - }; - } else { - return undefined; - } - } - - public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password - }; - } else { - return undefined; - } - } - - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); - }); - } - - protected async getAccountNode(context: IActionContext): Promise { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { - - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); - } - - return this._accountNode; - } -} diff --git a/src/commands/api/DatabaseTreeItemInternal.ts b/src/commands/api/DatabaseTreeItemInternal.ts deleted file mode 100644 index 9d6b0d140..000000000 --- a/src/commands/api/DatabaseTreeItemInternal.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; - -export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; - - constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } - - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); - } - - await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); - }); - } -} diff --git a/src/commands/api/apiCache.ts b/src/commands/api/apiCache.ts deleted file mode 100644 index 30da342aa..000000000 --- a/src/commands/api/apiCache.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; - -/** - * This cache is used to speed up api calls from other extensions to the Cosmos DB extension - * For now, it only helps on a per-session basis - */ -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = new Map(); - -export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { - sessionCache.set(parsedCS.fullId, treeItem); -} - -export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); -} - -export function removeTreeItemFromCache(expected: ParsedConnectionString): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); - } else { - actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); - } - if (actual && (actual.accountId === expected.accountId)) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } -} diff --git a/src/commands/api/findTreeItem.ts b/src/commands/api/findTreeItem.ts deleted file mode 100644 index 088413e52..000000000 --- a/src/commands/api/findTreeItem.ts +++ /dev/null @@ -1,146 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -export async function findTreeItem(query: TreeItemQuery): Promise { - return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, 'connectionString'); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = await rootNode.getCachedChildren(context); - result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - }); -} - -async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); - } - if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); - } else { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); - } - - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); - } else { - return new DatabaseAccountTreeItemInternal(expected, dbAccount); - } - - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; -} diff --git a/src/commands/api/pickTreeItem.ts b/src/commands/api/pickTreeItem.ts deleted file mode 100644 index dc84ce55a..000000000 --- a/src/commands/api/pickTreeItem.ts +++ /dev/null @@ -1,100 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; -import { databaseAccountType } from '../../constants'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { localize } from '../../utils/localize'; -import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; -function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case 'Mongo': - return MongoDatabaseTreeItem.contextValue; - case 'SQL': - return DocDBDatabaseTreeItem.contextValue; - case 'Graph': - return GraphDatabaseTreeItem.contextValue; - case 'Postgres': - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } -} - - -export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { - return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case 'Database': - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType ? - pickTreeOptions.apiType.map(getDatabaseContextValue) : - databaseContextValues; - break; - case 'DatabaseAccount': - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); - } - - const pickedItem = await ext.rgApi.pickAppResource(context, options); - - let parsedCS: ParsedConnectionString; - let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; - let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); - } - - const result = databaseNode ? - new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : - new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - }); -} diff --git a/src/commands/api/revealTreeItem.ts b/src/commands/api/revealTreeItem.ts deleted file mode 100644 index d13589351..000000000 --- a/src/commands/api/revealTreeItem.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { ext } from "../../extensionVariables"; - -export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); - } - }); -} diff --git a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts deleted file mode 100644 index 1ef9ca645..000000000 --- a/src/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; - -export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } - - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } -} diff --git a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts deleted file mode 100644 index 762beb96e..000000000 --- a/src/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; - -export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; -} diff --git a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts deleted file mode 100644 index a90956b30..000000000 --- a/src/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; -import { localize } from '../../utils/localize'; -import { IDeleteWizardContext } from './IDeleteWizardContext'; - -export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await deletePromise; - const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } else { - await deletePromise; - } -} diff --git a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts deleted file mode 100644 index 4792710d4..000000000 --- a/src/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; -import { createActivityContext } from "../../utils/activityUtils"; -import { localize } from "../../utils/localize"; -import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; -import { IDeleteWizardContext } from "./IDeleteWizardContext"; - - -export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()) - }); - - const title = wizardContext.deletePostgres ? - localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : - localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) - - const confirmationMessage = wizardContext.deletePostgres ? - localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : - localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); - - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()] - }); - - await wizard.prompt(); - await wizard.execute(); -} diff --git a/src/commands/importDocuments.ts b/src/commands/importDocuments.ts deleted file mode 100644 index bd4c83e3f..000000000 --- a/src/commands/importDocuments.ts +++ /dev/null @@ -1,163 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ItemDefinition } from '@azure/cosmos'; -import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { cosmosMongoFilter, sqlFilter } from '../constants'; -import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; -import { ext } from '../extensionVariables'; -import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { getRootPath } from '../utils/workspacUtils'; - -export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); - ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents..." - }, - async (progress) => { - uris = nonNullValue(uris, 'uris'); - collectionNode = nonNullValue(collectionNode, 'collectionNode'); - - progress.report({ increment: 20, message: "Parsing documents for errors" }); - const documents = await parseDocuments(uris); - progress.report({ increment: 30, message: "Parsed documents. Importing" }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo(collectionNode, documents); - } else { - result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); - - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); -} - -async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"] - } - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); - erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); - ext.outputChannel.show(); - throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); - } - for (const document of documents) { - const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; -} diff --git a/src/constants.ts b/src/constants.ts deleted file mode 100644 index 0e6a4a14e..000000000 --- a/src/constants.ts +++ /dev/null @@ -1,136 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export const isWindows: boolean = /^win/.test(process.platform); - -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; -import { ext } from './extensionVariables'; - -export namespace Links { - export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; -} - -export interface IThemedIconPath { - light: string; - dark: string; -} - -export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'light', iconName), - dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) - }; - assert(fs.existsSync(a.light)); - return a; -} - -export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), - dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) - }; - assert(fs.existsSync(a.light)); - return a; -} - -export function getResourcesPath(): string { - return ext.context.asAbsolutePath('resources'); -} - -export const doubleClickDebounceDelay = 500; //milliseconds - -export const defaultStoredProcedure = - `function sample(prefix) { - var collection = getContext().getCollection(); - - // Query documents and take 1st item. - var isAccepted = collection.queryDocuments( - collection.getSelfLink(), - 'SELECT * FROM root r', - function (err, feed, options) { - if (err) throw err; - - // Check the feed and if empty, set the body to 'no docs found', - // else take 1st element from feed - if (!feed || !feed.length) { - var response = getContext().getResponse(); - response.setBody('no docs found'); - } - - else { - var response = getContext().getResponse(); - var body = { prefix: prefix, feed: feed[0] }; - response.setBody(JSON.stringify(body)); - } - }); - - if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};` ; - -export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; - -// https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = 'test'; - -export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; -export const postgresLanguageId: string = 'postgres'; -export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = 'query'; -export const postgresDefaultPort = '5432'; -export const postgresDefaultDatabase = 'postgres'; -export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; - -export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; - -export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; - -export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag - } -}; - -export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; - -export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag - } -}; - -export const tableDefaultExperienceTag = 'Azure Table'; - -export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag - } -}; - -export const sqlDefaultExperienceTag = 'Core (SQL)'; - -export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag - } -}; - -export const postgresFlexibleFilter = { - type: 'Microsoft.DBforPostgreSQL/flexibleServers' -}; - -export const postgresSingleFilter = { - type: 'Microsoft.DBForPostgreSQL/servers' -}; diff --git a/src/docdb/docDBConnectionStrings.ts b/src/docdb/docDBConnectionStrings.ts deleted file mode 100644 index 946490d21..000000000 --- a/src/docdb/docDBConnectionStrings.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as url from 'url'; -import { ParsedConnectionString } from '../ParsedConnectionString'; -import { nonNullProp } from '../utils/nonNull'; - -export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); - const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); - const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); - if (!endpoint || !masterKey) { - throw new Error('Invalid Document DB connection string.'); - } - return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); -} - -function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; -} - -export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - public readonly documentEndpoint: string; - public readonly masterKey: string; - - constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; - - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, 'hostname'); - this.port = nonNullProp(parsedEndpoint, 'port'); - } -} diff --git a/src/docdb/getCosmosClient.ts b/src/docdb/getCosmosClient.ts deleted file mode 100644 index 3b285fc9c..000000000 --- a/src/docdb/getCosmosClient.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient } from "@azure/cosmos"; -import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; -import * as https from "https"; -import * as vscode from 'vscode'; -import { ext } from "../extensionVariables"; - -export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { - - const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; - return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); - -} diff --git a/src/docdb/registerDocDBCommands.ts b/src/docdb/registerDocDBCommands.ts deleted file mode 100644 index 5eb7545e4..000000000 --- a/src/docdb/registerDocDBCommands.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { commands } from "vscode"; -import { doubleClickDebounceDelay, sqlFilter } from "../constants"; -import { ext } from "../extensionVariables"; -import { DocDBAccountTreeItem } from "./tree/DocDBAccountTreeItem"; -import { DocDBCollectionTreeItem } from "./tree/DocDBCollectionTreeItem"; -import { DocDBDatabaseTreeItem } from "./tree/DocDBDatabaseTreeItem"; -import { DocDBDocumentsTreeItem } from "./tree/DocDBDocumentsTreeItem"; -import { DocDBDocumentTreeItem } from "./tree/DocDBDocumentTreeItem"; -import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeItem"; -import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; - -export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openDocument", documentNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); - } - const childNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - - } - await node.deleteTreeItem(context); - }); -} - -export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); - await databaseNode.createChild(context); -} - -export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.createChild(context); -} - -export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - sqlFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/docdb/tree/DocDBAccountTreeItem.ts b/src/docdb/tree/DocDBAccountTreeItem.ts deleted file mode 100644 index 0cee7ed06..000000000 --- a/src/docdb/tree/DocDBAccountTreeItem.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; - -export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; - - public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } -} diff --git a/src/docdb/tree/DocDBAccountTreeItemBase.ts b/src/docdb/tree/DocDBAccountTreeItemBase.ts deleted file mode 100644 index da9eec6b7..000000000 --- a/src/docdb/tree/DocDBAccountTreeItemBase.ts +++ /dev/null @@ -1,95 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { rejectOnTimeout } from '../../utils/timeout'; -import { getCosmosClient } from '../getCosmosClient'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class provides common logic for DocumentDB, Graph, and Table accounts - * (DocumentDB is the base type for all Cosmos DB accounts) - */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; - - - constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) - }; - - this.valuesToMask.push(id, endpoint, masterKey); - } - - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public get isServerless(): boolean { - return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; - - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.databases.readAll(feedOptions); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: 'Database Name', - validateInput: validateDatabaseName, - stepName: 'createDatabase' - }); - - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ id: databaseName }); - return this.initChild(nonNullProp(database, 'resource')); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } -} - -function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; -} diff --git a/src/docdb/tree/DocDBCollectionTreeItem.ts b/src/docdb/tree/DocDBCollectionTreeItem.ts deleted file mode 100644 index 987bbe3b4..000000000 --- a/src/docdb/tree/DocDBCollectionTreeItem.ts +++ /dev/null @@ -1,92 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * Represents a DocumentDB collection - */ -export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - } -} diff --git a/src/docdb/tree/DocDBDatabaseTreeItem.ts b/src/docdb/tree/DocDBDatabaseTreeItem.ts deleted file mode 100644 index ee8c23694..000000000 --- a/src/docdb/tree/DocDBDatabaseTreeItem.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; - -export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Collection'; - - public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } - - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } -} diff --git a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts b/src/docdb/tree/DocDBDatabaseTreeItemBase.ts deleted file mode 100644 index aa7e8d779..000000000 --- a/src/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ /dev/null @@ -1,161 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -const minThroughputFixed: number = 400; -const minThroughputPartitioned: number = 400; -const maxThroughput: number = 100000; -const throughputStepSize = 100; - -/** - * This class provides common logic for DocumentDB, Graph, and Table databases - * (DocumentDB is the base type for all Cosmos DB accounts) - */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public get id(): string { - return nonNullProp(this._database, 'id'); - } - - public get label(): string { - return nonNullProp(this._database, 'id'); - } - - public get link(): string { - return nonNullProp(this._database, '_self'); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.database(this._database.id).containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl(context: ICreateChildImplContext): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}` - }); - - const containerDefinition: ContainerDefinition = { - id: containerName - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey] - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !(containerDefinition.partitionKey); - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const throughput: number = Number(await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: 'throughputCapacity', - validateInput: (input: string) => validateThroughput(isFixed, input) - })); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, 'resource')); - } - - protected async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address/zipCode' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } -} - -function validateThroughput(isFixed: boolean, input: string): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const value = Number(input); - if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; -} - -function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; -} diff --git a/src/docdb/tree/DocDBDocumentTreeItem.ts b/src/docdb/tree/DocDBDocumentTreeItem.ts deleted file mode 100644 index 1505572d9..000000000 --- a/src/docdb/tree/DocDBDocumentTreeItem.ts +++ /dev/null @@ -1,133 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { sanitizeId } from './DocDBUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; - -/** - * Represents a Cosmos DB DocumentDB (SQL) document - */ -export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openDocument'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error(`The "_self" and "_etag" fields are required to update a document`); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; - const response = await this.getDocumentClient(client).replace(newData, options); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split('/'); - if (fields[0] === '') { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { //Partition Key exists, but this document doesn't have a value - return ''; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); - } -} diff --git a/src/docdb/tree/DocDBDocumentsTreeItem.ts b/src/docdb/tree/DocDBDocumentsTreeItem.ts deleted file mode 100644 index b8265444d..000000000 --- a/src/docdb/tree/DocDBDocumentsTreeItem.ts +++ /dev/null @@ -1,129 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; -import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class provides logic for DocumentDB collections - */ -export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = (await this.promptForPartitionKey(context, body)); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); - return nonNullProp(item, 'resource'); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split('/'); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { - const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: 'valueforParititionKey' - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { - //remove leading slash - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split('/'); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } -} diff --git a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts b/src/docdb/tree/DocDBStoredProcedureTreeItem.ts deleted file mode 100644 index 899eccd27..000000000 --- a/src/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from "vscode"; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * Represents a Cosmos DB DocumentDB (SQL) stored procedure - */ -export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); - - constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openStoredProcedure'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get filePath(): string { - return this.label + '-cosmos-stored-procedure.js'; - } - - public get id(): string { - return this.procedure.id; - } - - public get label(): string { - return this.procedure.id; - } - - public get link(): string { - return this.procedure._self; - } - - public async getFileContent(): Promise { - return typeof this.procedure.body === 'string' ? this.procedure.body : ''; - - } - - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, 'resource'); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); - } -} diff --git a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts b/src/docdb/tree/DocDBStoredProceduresTreeItem.ts deleted file mode 100644 index 4c3ddfd1a..000000000 --- a/src/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from "vscode"; -import { defaultStoredProcedure } from '../../constants'; -import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; - -/** - * This class represents the DocumentDB "Stored Procedures" node in the tree - */ -export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = (await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: 'createStoredProcedure', - validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) - })).trim(); - const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; - context.showCreatingTreeItem(spID); - const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, 'resource')); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize("nameLength", "Name has to be between 1 and 255 chars long"); - } - - if (/[/\\?#&]/.test(name)) { - return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); - } - - return undefined; - } -} diff --git a/src/docdb/tree/DocDBTreeItemBase.ts b/src/docdb/tree/DocDBTreeItemBase.ts deleted file mode 100644 index 4424603ae..000000000 --- a/src/docdb/tree/DocDBTreeItemBase.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -/** - * This class provides common iteration logic for DocumentDB accounts, databases, and collections - */ -export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; - - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public root: IDocDBTreeRoot; - - public abstract initChild(resource: T): AzExtTreeItem; - - public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); - } - - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); - - this._batchSize *= 2; - - return resourceArray.map((resource: T) => this.initChild(resource)); - } -} diff --git a/src/docdb/tree/DocDBUtils.ts b/src/docdb/tree/DocDBUtils.ts deleted file mode 100644 index 3d45cf950..000000000 --- a/src/docdb/tree/DocDBUtils.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/** - * Sanitize an the id of a DocDB tree item so it can be safely used in a query string. - * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding - */ -export function sanitizeId(id: string): string { - return id.replace(/\+/g, ' '); -} diff --git a/src/docdb/tree/IDocDBTreeRoot.ts b/src/docdb/tree/IDocDBTreeRoot.ts deleted file mode 100644 index 9179eb454..000000000 --- a/src/docdb/tree/IDocDBTreeRoot.ts +++ /dev/null @@ -1,14 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosClient } from "@azure/cosmos"; - -export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; -} diff --git a/src/extension.ts b/src/extension.ts deleted file mode 100644 index e68744157..000000000 --- a/src/extension.ts +++ /dev/null @@ -1,215 +0,0 @@ -/*-------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; -import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; -import { platform } from 'os'; -import * as vscode from 'vscode'; -import { DatabasesFileSystem } from './DatabasesFileSystem'; -import { findTreeItem } from './commands/api/findTreeItem'; -import { pickTreeItem } from './commands/api/pickTreeItem'; -import { revealTreeItem } from './commands/api/revealTreeItem'; -import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { importDocuments } from './commands/importDocuments'; -import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; -import { registerDocDBCommands } from './docdb/registerDocDBCommands'; -import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; -import { ext } from './extensionVariables'; -import { getResourceGroupsApi } from './getExtensionApi'; -import { registerGraphCommands } from './graph/registerGraphCommands'; -import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; -import { registerMongoCommands } from './mongo/registerMongoCommands'; -import { setConnectedNode } from './mongo/setConnectedNode'; -import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; -import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; -import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; -import { DatabaseResolver } from './resolver/AppResolver'; -import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; -import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; -import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; -import { localize } from './utils/localize'; - -const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; - -export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = 'true'; - activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); - - const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); - ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { - if (platform() !== 'win32') { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); - } - - await ext.attachedAccountsNode.attachEmulator(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh(actionContext, node); - } - }); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { - const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); - if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { - const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); - } - if (node instanceof MongoAccountTreeItem) { - if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments(actionContext, uris || [selectedNode], undefined); - } else { - await importDocuments(actionContext, undefined, selectedNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { - if (!node) { - node = await ext.rgApi.pickAppResource(actionContext, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); - registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); - registerEvent( - 'cosmosDB.onDidChangeConfiguration', - vscode.workspace.onDidChangeConfiguration, - async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { - actionContext.telemetry.properties.isActivationEvent = "true"; - actionContext.errorHandling.suppressDisplay = true; - if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { - await vscode.commands.executeCommand("azureDatabases.refresh"); - } - }); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); - registerReportIssueCommand('azureDatabases.reportIssue'); - }); - - return createApiProvider([{ - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: '1.2.0' - }]); -} - -// this method is called when your extension is deactivated -export function deactivateInternal(): void { - // NOOP -} - -export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { - if (!node) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); - } - - await SubscriptionTreeItem.createChild(context, node); -} - -export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await deleteDatabaseAccount(context, node, false) -} - -export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { - const message = 'The connection string has been copied to the clipboard'; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); -} diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts deleted file mode 100644 index 4a3fc2650..000000000 --- a/src/extensionVariables.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; -import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; -import { ExtensionContext, SecretStorage, TreeView } from "vscode"; -import { DatabasesFileSystem } from "./DatabasesFileSystem"; -import { MongoDBLanguageClient } from "./mongo/languageClient"; -import { MongoCodeLensProvider } from "./mongo/services/MongoCodeLensProvider"; -import { MongoDatabaseTreeItem } from "./mongo/tree/MongoDatabaseTreeItem"; -import { PostgresCodeLensProvider } from "./postgres/services/PostgresCodeLensProvider"; -import { PostgresDatabaseTreeItem } from "./postgres/tree/PostgresDatabaseTreeItem"; -import { AttachedAccountsTreeItem } from "./tree/AttachedAccountsTreeItem"; -import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWithAttached"; - -/** - * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts - */ -export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = 'azureDatabases'; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; - - export namespace settingsKeys { - export const mongoShellPath = 'mongo.shell.path'; - export const mongoShellArgs = 'mongo.shell.args'; - export const documentLabelFields = 'cosmosDB.documentLabelFields'; - export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; - export const mongoShellTimeout = 'mongo.shell.timeout'; - export const batchSize = 'azureDatabases.batchSize'; - - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } -} diff --git a/src/getExtensionApi.ts b/src/getExtensionApi.ts deleted file mode 100644 index bfd553e74..000000000 --- a/src/getExtensionApi.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { apiUtils } from "@microsoft/vscode-azext-utils"; -import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; -import { Extension, extensions } from "vscode"; -import { localize } from "./utils/localize"; - -export async function getApiExport(extensionId: string): Promise { - const extension: Extension | undefined = extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } - - return extension.exports; - } - - return undefined; -} - -export async function getResourceGroupsApi(): Promise { - const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); - if (rgApiProvider) { - return rgApiProvider.getApi('0.0.1'); - } else { - throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); - } -} diff --git a/src/graph/gremlinEndpoints.ts b/src/graph/gremlinEndpoints.ts deleted file mode 100644 index 1ef6b283d..000000000 --- a/src/graph/gremlinEndpoints.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { nonNullValue } from '../utils/nonNull'; -import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; - -export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; -} - -export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - - const documentSuffix = '.documents.azure.com'; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); - - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); - - return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } -} - -/** - * Parses a IGremlinPoint from a URL - * @param url An account URL such as 'https://.documents.azure.com:443/' - */ -function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; -} diff --git a/src/graph/registerGraphCommands.ts b/src/graph/registerGraphCommands.ts deleted file mode 100644 index 1746c638b..000000000 --- a/src/graph/registerGraphCommands.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; -import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; -import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; -import { GraphTreeItem } from "./tree/GraphTreeItem"; - -export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph(context, GraphTreeItem.contextValue); - } - await node.showExplorer(context); - }, doubleClickDebounceDelay); -} - -export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); -} - -export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.createChild(context); -} - -async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosGremlinFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/graph/tree/GraphAccountTreeItem.ts b/src/graph/tree/GraphAccountTreeItem.ts deleted file mode 100644 index 7e1f561fa..000000000 --- a/src/graph/tree/GraphAccountTreeItem.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; - -export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } - - public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } -} diff --git a/src/graph/tree/GraphCollectionTreeItem.ts b/src/graph/tree/GraphCollectionTreeItem.ts deleted file mode 100644 index 63709d977..000000000 --- a/src/graph/tree/GraphCollectionTreeItem.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; - -export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - - } -} diff --git a/src/graph/tree/GraphDatabaseTreeItem.ts b/src/graph/tree/GraphDatabaseTreeItem.ts deleted file mode 100644 index 1c5332700..000000000 --- a/src/graph/tree/GraphDatabaseTreeItem.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; -import { GraphAccountTreeItem } from './GraphAccountTreeItem'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; - -export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Graph'; - - constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { - super(parent, database); - } - - public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } - - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } - - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } - - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - - } - - protected override async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } -} diff --git a/src/graph/tree/GraphTreeItem.ts b/src/graph/tree/GraphTreeItem.ts deleted file mode 100644 index 800fded5a..000000000 --- a/src/graph/tree/GraphTreeItem.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ContainerDefinition, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; - -const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; - -export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this.commandId = 'cosmosDB.openGraphExplorer'; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } -} diff --git a/src/mongo/MongoCommand.ts b/src/mongo/MongoCommand.ts deleted file mode 100644 index 79c33731f..000000000 --- a/src/mongo/MongoCommand.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { RecognitionException } from 'antlr4ts'; -import * as vscode from 'vscode'; - -export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; -} - -export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; -} diff --git a/src/mongo/MongoScrapbook.ts b/src/mongo/MongoScrapbook.ts deleted file mode 100644 index d5dfe6d00..000000000 --- a/src/mongo/MongoScrapbook.ts +++ /dev/null @@ -1,491 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ObjectID } from 'bson'; -import { Collection } from 'mongodb'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { filterType, findType } from '../utils/array'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { mongoLexer } from './grammar/mongoLexer'; -import * as mongoParser from './grammar/mongoParser'; -import { MongoVisitor } from './grammar/visitors'; -import { ErrorDescription, MongoCommand } from './MongoCommand'; -import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; -import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of (command.errors || [])) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; -} - -export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); -} - -export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); - return await executeCommand(context, command); -} - -function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } -} - -export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { - return getAllCommandsFromText(document.getText()); -} - -async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { - const label: string = 'Scrapbook-execute-all-results'; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } -} - -async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === 'find' && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, 'collection'); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); - await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === 'findOne') { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp(command, 'collection'); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); - if (!colNode) { - throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = 'Scrapbook-results'; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error('No MongoDB command found at the current cursor location.'); - } -} - -async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { - if (command.name === 'drop') { - await database.refresh(context); - } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); - if (collectionNode) { - await collectionNode.refresh(context); - } - } -} - -export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "" - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; -} - -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; -} - -class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop'); - this.commands.push({ - range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); - return {}; - } - } - - private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' - this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); - if (argumentContextArray.length > 1) { - this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); - return {}; - } - } - - private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { - if (!tokenText) { // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop'); - const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* - We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. - $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. - {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). - We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those - What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. - */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } - -} diff --git a/src/mongo/MongoShell.ts b/src/mongo/MongoShell.ts deleted file mode 100644 index b8f982ee8..000000000 --- a/src/mongo/MongoShell.ts +++ /dev/null @@ -1,187 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; -import { randomUtils } from '../utils/randomUtils'; -import { getBatchSizeSetting } from '../utils/workspacUtils'; -import { wrapError } from '../utils/wrapError'; - -const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; - -const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = '(More)'; - -const sentinelBase = 'EXECUTION COMPLETED'; -const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } - -export class MongoShell extends vscode.Disposable { - - constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { - super(() => this.dispose()); - } - - public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '' - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut(text => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); - - resolve(stdOutNoSentinel); - } - })); - disposables.push( - this._process.onStdErr(text => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - })); - disposables.push( - this._process.onError(error => { - reject(error); - })); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error("The process exited prematurely."); - } - - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } - finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } -} - -function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout( - () => { - reject(timeoutMessage); - }, - timeoutSeconds * 1000); - } -} - -function convertToSingleLine(script: string): string { - return script.split(os.EOL) - .map(line => line.trim()) - .join(''); - -} - -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} - -function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); -} diff --git a/src/mongo/connectToMongoClient.ts b/src/mongo/connectToMongoClient.ts deleted file mode 100644 index 88aa2df17..000000000 --- a/src/mongo/connectToMongoClient.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { MongoClient, MongoClientOptions } from 'mongodb'; -import { emulatorPassword, Links } from '../constants'; - -export async function connectToMongoClient(connectionString: string, appName: string): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string, name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - throw error; - } -} - -export class MongoConnectError extends Error { - constructor() { - super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); - } -} - -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); -} diff --git a/src/mongo/errorListeners.ts b/src/mongo/errorListeners.ts deleted file mode 100644 index ea582d544..000000000 --- a/src/mongo/errorListeners.ts +++ /dev/null @@ -1,67 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { Recognizer } from 'antlr4ts/Recognizer'; -import { Token } from 'antlr4ts/Token'; -import * as vscode from "vscode"; -import { ErrorDescription } from './MongoCommand'; - -export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { - - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } -} - -export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { - - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } -} diff --git a/src/mongo/grammar/mongo.tokens b/src/mongo/grammar/mongo.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/mongo/grammar/mongo.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/mongo/grammar/mongoLexer.tokens b/src/mongo/grammar/mongoLexer.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/mongo/grammar/mongoLexer.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/mongo/grammar/mongoLexer.ts b/src/mongo/grammar/mongoLexer.ts deleted file mode 100644 index 3b6cbbdd0..000000000 --- a/src/mongo/grammar/mongoLexer.ts +++ /dev/null @@ -1,247 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { RuleContext } from 'antlr4ts/RuleContext'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; - - - -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = [ - "DEFAULT_MODE" - ]; - - public static readonly ruleNames: string[] = [ - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", - "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", - "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", - "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", - "ExponentPart", "DecimalDigit", "WHITESPACE" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoLexer.ruleNames; } - - @Override - public get serializedATN(): string { return mongoLexer._serializedATN; } - - @Override - public get modeNames(): string[] { return mongoLexer.modeNames; } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text) - ; - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } - -} - diff --git a/src/mongo/grammar/mongoListener.ts b/src/mongo/grammar/mongoListener.ts deleted file mode 100644 index 43514f500..000000000 --- a/src/mongo/grammar/mongoListener.ts +++ /dev/null @@ -1,208 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - - -import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - - -/** - * This interface defines a complete listener for a parse tree produced by - * `mongoParser`. - */ -export interface mongoListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - enterMongoCommands?: (ctx: MongoCommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - exitMongoCommands?: (ctx: MongoCommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - enterCommands?: (ctx: CommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - exitCommands?: (ctx: CommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - enterCommand?: (ctx: CommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - exitCommand?: (ctx: CommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - enterEmptyCommand?: (ctx: EmptyCommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - exitEmptyCommand?: (ctx: EmptyCommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - enterCollection?: (ctx: CollectionContext) => void; - /** - * Exit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - exitCollection?: (ctx: CollectionContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - enterFunctionCall?: (ctx: FunctionCallContext) => void; - /** - * Exit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - exitFunctionCall?: (ctx: FunctionCallContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - enterArguments?: (ctx: ArgumentsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - exitArguments?: (ctx: ArgumentsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - enterArgument?: (ctx: ArgumentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - exitArgument?: (ctx: ArgumentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - enterObjectLiteral?: (ctx: ObjectLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - exitObjectLiteral?: (ctx: ObjectLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - enterArrayLiteral?: (ctx: ArrayLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - exitArrayLiteral?: (ctx: ArrayLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - enterElementList?: (ctx: ElementListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - exitElementList?: (ctx: ElementListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - enterPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - exitPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - enterPropertyValue?: (ctx: PropertyValueContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - exitPropertyValue?: (ctx: PropertyValueContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - enterLiteral?: (ctx: LiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - exitLiteral?: (ctx: LiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - enterPropertyName?: (ctx: PropertyNameContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - exitPropertyName?: (ctx: PropertyNameContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - enterComment?: (ctx: CommentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - exitComment?: (ctx: CommentContext) => void; -} - diff --git a/src/mongo/grammar/mongoParser.ts b/src/mongo/grammar/mongoParser.ts deleted file mode 100644 index c1d38f4d0..000000000 --- a/src/mongo/grammar/mongoParser.ts +++ /dev/null @@ -1,1466 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { TokenStream } from 'antlr4ts/TokenStream'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { mongoListener } from './mongoListener'; -import { mongoVisitor } from './mongoVisitor'; - - - - -export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", "commands", "command", "emptyCommand", "collection", - "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", - "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", - "literal", "propertyName", "comment" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoParser.ruleNames; } - - @Override - public get serializedATN(): string { return mongoParser._serializedATN; } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + - "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } - -} - -export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } -} - - -export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } -} - - -export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_command; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } -} - - -export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } -} - - -export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } -} - - -export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } -} - - -export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } -} - - -export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } -} - - -export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } -} - - -export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } - public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } - public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } -} - - -export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } -} - - -export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } - public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } -} - - diff --git a/src/mongo/grammar/mongoVisitor.ts b/src/mongo/grammar/mongoVisitor.ts deleted file mode 100644 index eb001a6e9..000000000 --- a/src/mongo/grammar/mongoVisitor.ts +++ /dev/null @@ -1,143 +0,0 @@ -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - - -import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by `mongoParser`. - * - * @param The return type of the visit operation. Use `void` for - * operations with no return type. - */ -export interface mongoVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitMongoCommands?: (ctx: MongoCommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommands?: (ctx: CommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommand?: (ctx: CommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - * @return the visitor result - */ - visitEmptyCommand?: (ctx: EmptyCommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCollection?: (ctx: CollectionContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFunctionCall?: (ctx: FunctionCallContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArguments?: (ctx: ArgumentsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArgument?: (ctx: ArgumentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitObjectLiteral?: (ctx: ObjectLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArrayLiteral?: (ctx: ArrayLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitElementList?: (ctx: ElementListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyAssignment?: (ctx: PropertyAssignmentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyValue?: (ctx: PropertyValueContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - * @return the visitor result - */ - visitLiteral?: (ctx: LiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyName?: (ctx: PropertyNameContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitComment?: (ctx: CommentContext) => Result; -} - diff --git a/src/mongo/grammar/visitors.ts b/src/mongo/grammar/visitors.ts deleted file mode 100644 index e1ba1b63d..000000000 --- a/src/mongo/grammar/visitors.ts +++ /dev/null @@ -1,83 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; -import { mongoVisitor } from './mongoVisitor'; - -export class MongoVisitor implements mongoVisitor { - - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return null; - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } -} diff --git a/src/mongo/languageClient.ts b/src/mongo/languageClient.ts deleted file mode 100644 index e4bd4aefd..000000000 --- a/src/mongo/languageClient.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -import * as nls from 'vscode-nls'; -import { ext } from '../extensionVariables'; -import { IConnectionParams } from './services/IConnectionParams'; - -const localize = nls.loadMessageBundle(); - -export class MongoDBLanguageClient { - - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle ? - ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : - ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'mongo', scheme: 'file' }, - { language: 'mongo', scheme: 'untitled' } - ] - }; - - // Create the language client and start the client. - this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect(connectionString: string, databaseName: string): Promise { - await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } -} diff --git a/src/mongo/languageServer.ts b/src/mongo/languageServer.ts deleted file mode 100644 index d5d6ec484..000000000 --- a/src/mongo/languageServer.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from 'vscode-languageserver'; -import { LanguageService } from './services/languageService'; - -// -// -// -// HOW TO DEBUG THE LANGUAGE SERVER -// -// -// 1. Start the extension via F5 -// 2. Under vscode Debug pane, switch to "Attach to Language Server" -// 3. F5 -// -// -// - -// Create a connection for the server -const connection: IConnection = createConnection(); -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -console.log = connection.console.log.bind(connection.console); -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -console.error = connection.console.error.bind(connection.console); - -new LanguageService(connection); - -// Listen on the connection -connection.listen(); diff --git a/src/mongo/mongoConnectionStrings.ts b/src/mongo/mongoConnectionStrings.ts deleted file mode 100644 index 5f73db484..000000000 --- a/src/mongo/mongoConnectionStrings.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; -import { MongoClient } from "mongodb"; -import { testDb } from "../constants"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullValue } from "../utils/nonNull"; -import { connectToMongoClient } from "./connectToMongoClient"; - -// Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): -// mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] -// Some example connection strings: -// mongodb://dbuser:dbpassword@dbname.mlab.com:14118 -// mongodb+srv://db1.example.net:27017,db2.example.net:2500/?replicaSet=test -// mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/database?ssh=true -// Regex splits into three parts: -// Full match -// mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] -// [database] - -const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; -const parseDatabaseName = '\/?([^/?]+)?'; -const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); - -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } - - return undefined; -} - -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } -} - -export async function parseMongoConnectionString(connectionString: string): Promise { - - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; - - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - - return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); -} - -export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } -} - -/** - * Encodes the username and password in the given Mongo DB connection string. - */ -export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } - - return connectionString; -} diff --git a/src/mongo/registerMongoCommands.ts b/src/mongo/registerMongoCommands.ts deleted file mode 100644 index 2dc36477a..000000000 --- a/src/mongo/registerMongoCommands.ts +++ /dev/null @@ -1,223 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { Experience, MongoExperience } from '../AzureDBExperiences'; -import { cosmosMongoFilter } from "../constants"; -import { ext } from "../extensionVariables"; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { MongoConnectError } from './connectToMongoClient'; -import { MongoDBLanguageClient } from "./languageClient"; -import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; -import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; -import { setConnectedNode } from "./setConnectedNode"; -import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; -import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; -import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; - -const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; -let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = 'mongo'; - -export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); - } - - const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); - if (oldNode) { - await oldNode.refresh(context); - } - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); - registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - }); -} - -async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); -} - -function launchMongoShell(): void { - const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); - terminal.sendText(`mongo`); - terminal.show(); -} - -function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }); - - // Update errors when document opened/changed - registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); -} - -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } -} - -export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); - - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); -} - -export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); -} - -export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } -} - -export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); -} - -async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter - ], - expectedChildContextValue: expectedContextValue - }); -} diff --git a/src/mongo/services/IConnectionParams.ts b/src/mongo/services/IConnectionParams.ts deleted file mode 100644 index eec39e4cf..000000000 --- a/src/mongo/services/IConnectionParams.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; -} diff --git a/src/mongo/services/MongoCodeLensProvider.ts b/src/mongo/services/MongoCodeLensProvider.ts deleted file mode 100644 index 3407c50dd..000000000 --- a/src/mongo/services/MongoCodeLensProvider.ts +++ /dev/null @@ -1,75 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from "vscode"; -import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; - -export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; - - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } - - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } - - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; - - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; - - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized ? - 'Initializing...' : - isConnected ? - `Connected to ${database}` : - `Connect to a database`, - command: isInitialized && 'cosmosDB.connectMongoDB' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); - - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: 'cosmosDB.executeAllMongoCommands' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); - - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: 'cosmosDB.executeMongoCommand', - arguments: [cmd.range.start] - }, - range: cmd.range - }); - } - } - - return lenses; - }); - } -} diff --git a/src/mongo/services/completionItemProvider.ts b/src/mongo/services/completionItemProvider.ts deleted file mode 100644 index cba51890c..000000000 --- a/src/mongo/services/completionItemProvider.ts +++ /dev/null @@ -1,439 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-non-null-assertion */ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) - .then(list => { - return list!.items.map(item => { - const startPositionOffset = document.offsetAt(item.textEdit!.range.start); - const endPositionOffset = document.offsetAt(item.textEdit!.range.end); - item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range - }, - kind: CompletionItemKind.Keyword, - label: 'db' - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range) - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then(collections => { - return collections.map(collection => ({ - textEdit: { - newText: collection.collectionName, - range - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}` - })); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range) - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}` - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } - -} diff --git a/src/mongo/services/languageService.ts b/src/mongo/services/languageService.ts deleted file mode 100644 index 83b1b594e..000000000 --- a/src/mongo/services/languageService.ts +++ /dev/null @@ -1,90 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) - -import { Db } from 'mongodb'; -import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; -import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; - -export class LanguageService { - - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] } - } - }; - }); - - connection.onCompletion(textDocumentPosition => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) - .then(account => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db) - .then(schemas => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: uri => this.schemaService.resolveSchema(uri), - contributions: [] - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas - }); - } -} diff --git a/src/mongo/services/mongoScript.ts b/src/mongo/services/mongoScript.ts deleted file mode 100644 index 8d4c85398..000000000 --- a/src/mongo/services/mongoScript.ts +++ /dev/null @@ -1,101 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, Position } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { SchemaService } from './schemaService'; - -export class MongoScriptDocumentManager { - - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - } - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } -} - -export class MongoScriptDocument { - - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } - - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); - - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); - } - return Promise.resolve([]); - } -} - -class NodeFinder extends MongoVisitor { - - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; - const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; - const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; - const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; - - if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } -} diff --git a/src/mongo/services/schemaService.ts b/src/mongo/services/schemaService.ts deleted file mode 100644 index cf70e8cde..000000000 --- a/src/mongo/services/schemaService.ts +++ /dev/null @@ -1,628 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ - -import { Cursor, Db } from 'mongodb'; -import { SchemaConfiguration } from 'vscode-json-languageservice'; -// eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; - -export class SchemaService { - - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections() - .then(collections => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push(...[{ - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)] - }, { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)] - }]); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {} - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - for (const property of Object.keys(document)) { - if (!parent && - ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'] - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' - }, - $language: { - type: 'string', - description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' - }, - $caseSensitive: { - type: 'boolean', - description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` - } - }, - required: ['$search'] - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate' - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri - } - }; - schema.properties!.$and = { - type: 'array', - description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri - } - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri - } - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {} - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value' - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value' - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value' - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value' - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value' - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value' - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array' - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array' - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field' - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type' - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0] - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression' - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type' - }, - coordinates: { - type: 'array' - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string' - }, - properties: { - type: 'object' - } - } - } - } - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array' - }, - $polygon: { - type: 'array' - }, - $center: { - type: 'array' - }, - $centerSphere: { - type: 'array' - } - } - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema - } - }; - expressionSchema.properties.$near = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query' - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size' - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties } - }; - schema.properties!.$elemMatch = { - type: 'object' - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view' - } - } - - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri - } - } - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'] - } - }, - additionalProperties: { - type: 'object' - } - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' - } - } - }); - return { - type: 'object', - oneOf: schemas - }; - } - - private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then(hasNext => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then(doc => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } - -} diff --git a/src/mongo/setConnectedNode.ts b/src/mongo/setConnectedNode.ts deleted file mode 100644 index f5680d09d..000000000 --- a/src/mongo/setConnectedNode.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from "../extensionVariables"; -import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; - -export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); -} diff --git a/src/mongo/tree/IMongoTreeRoot.ts b/src/mongo/tree/IMongoTreeRoot.ts deleted file mode 100644 index d9b68980d..000000000 --- a/src/mongo/tree/IMongoTreeRoot.ts +++ /dev/null @@ -1,9 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface IMongoTreeRoot { - isEmulator: boolean | undefined; -} diff --git a/src/mongo/tree/MongoAccountTreeItem.ts b/src/mongo/tree/MongoAccountTreeItem.ts deleted file mode 100644 index baa870c23..000000000 --- a/src/mongo/tree/MongoAccountTreeItem.ts +++ /dev/null @@ -1,140 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; -import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; - -export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error('Missing connection string'); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); - - const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [{ - name: databaseInConnectionString, - empty: false - }]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); - databases = result.databases; - } - return databases - .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty - .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } - finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createMongoDatabase', - validateInput: validateDatabaseName - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } -} - -export function validateDatabaseName(database: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return "Database name cannot contain these characters - `/\\. \"$#?=`"; - } - return undefined; -} - -export interface IDatabaseInfo { - name?: string; - empty?: boolean; -} diff --git a/src/mongo/tree/MongoCollectionTreeItem.ts b/src/mongo/tree/MongoCollectionTreeItem.ts deleted file mode 100644 index eca0c8d32..000000000 --- a/src/mongo/tree/MongoCollectionTreeItem.ts +++ /dev/null @@ -1,320 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullValue } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { MongoCommand } from '../MongoCommand'; -import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; -type MongoDocument = { _id: string }; -class FunctionDescriptor { - public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { - } -} - -export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, '_id'), - upsert: false - } - }; - }); - - const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = await this.getCachedChildren(context); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(children.map(c => c.document), null, 2); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get filePath(): string { - return this.label + '-cosmos-collection.json'; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { - const documentNodes = await this.getCachedChildren(context); - for (const doc of docs) { - const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection.find(this._query).batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - 'invalidMongoDocument', - doc => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; - - const functions = { - drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), - count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), - findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), - insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), - insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), - insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), - deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), - deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), - remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error(`Too few arguments passed to command ${command.name}.`); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error(`Too many arguments passed to command ${command.name}`); - } - if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number, name?: string } = e; - const NamespaceNotFoundCode = 26; - if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne(query?: Object, fieldsOption?: Object): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, '\t'); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error("The insert command requires at least one argument"); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count(query?: Object[], options?: MongoCountPreferences): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, '\t'); - } -} - -function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title - }, - (_progress) => { - return promise; - }); -} - -function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } -} diff --git a/src/mongo/tree/MongoDatabaseTreeItem.ts b/src/mongo/tree/MongoDatabaseTreeItem.ts deleted file mode 100644 index 73a7c6a22..000000000 --- a/src/mongo/tree/MongoDatabaseTreeItem.ts +++ /dev/null @@ -1,258 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import { Collection, Db, DbCollectionOptions } from 'mongodb'; -import * as path from 'path'; -import * as process from 'process'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { MongoCommand } from '../MongoCommand'; -import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; -import { MongoShell } from '../MongoShell'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoAccountTreeItem } from './MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; -const executingInShellMsg = "Executing command in Mongo shell"; - -export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map(collection => new MongoCollectionTreeItem(this, collection)); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: 'createMongoCollection', - validateInput: validateMongoCollectionName - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); - return accountConnection.db(this.databaseName); - } - - public async executeCommand(command: MongoCommand, context: IActionContext): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); - const result = await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - - } - - if (command.name === 'createCollection') { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); - } else { - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - } - } - - public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection(collectionName, options); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); - - if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); - return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); - } - - private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongo', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongo'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; - const browse: vscode.MessageItem = { title: 'Open installation page' }; - const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; - const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; - const tryAgain: vscode.MessageItem = { title: 'Try again' }; - const response2 = await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } -} - -export function validateMongoCollectionName(collectionName: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; -} - -function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title - }, - (_progress) => { - return promise; - }); -} - -export function stripQuotes(term: string): string { - if ((term.startsWith('\'') && term.endsWith('\'')) - || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; -} diff --git a/src/mongo/tree/MongoDocumentTreeItem.ts b/src/mongo/tree/MongoDocumentTreeItem.ts deleted file mode 100644 index ad44e43c3..000000000 --- a/src/mongo/tree/MongoDocumentTreeItem.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires -const EJSON = require("mongodb-extended-json"); - -export interface IMongoDocument { - _id: string | ObjectID; - - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; -} - -export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private _label: string; - - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = 'cosmosDB.openDocument'; - ext.fileSystem.fireChangedEvent(this); - } - - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } - - public get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public static async update(collection: Collection, newDocument: IMongoDocument): Promise { - if (!newDocument._id) { - throw new Error(`The "_id" field is required to update a document.`); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); - if (result.modifiedCount !== 1) { - throw new Error(`Failed to update document with _id '${newDocument._id}'.`); - } - return newDocument; - } - - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); - const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error(`Failed to delete document with _id '${this.document._id}'.`); - } - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); - } -} diff --git a/src/postgres/abstract/AbstractPostgresClient.ts b/src/postgres/abstract/AbstractPostgresClient.ts deleted file mode 100644 index c1fa29c4f..000000000 --- a/src/postgres/abstract/AbstractPostgresClient.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; -import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; -import { PostgresServerType } from "./models"; - -export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; - -export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context) - case PostgresServerType.Single: - return await createPostgreSQLClient(context) - default: - throw new Error("Service not implemented."); - } -} diff --git a/src/postgres/abstract/models.ts b/src/postgres/abstract/models.ts deleted file mode 100644 index 6bdadf16a..000000000 --- a/src/postgres/abstract/models.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; - -export enum PostgresServerType { - Flexible = 'Flexible', - Single = 'Single' -} - -export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } - -export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; - -/** - * Billing information related properties of a server. - */ -export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; -} - -export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; -} - -export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; - -export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; diff --git a/src/postgres/commands/checkAuthentication.ts b/src/postgres/commands/checkAuthentication.ts deleted file mode 100644 index 6799d060c..000000000 --- a/src/postgres/commands/checkAuthentication.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { invalidCredentialsErrorType } from "../postgresConstants"; -import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { configurePostgresFirewall } from "./configurePostgresFirewall"; -import { enterPostgresCredentials } from "./enterPostgresCredentials"; - -export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); - - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; -} diff --git a/src/postgres/commands/configurePostgresFirewall.ts b/src/postgres/commands/configurePostgresFirewall.ts deleted file mode 100644 index 52a378fca..000000000 --- a/src/postgres/commands/configurePostgresFirewall.ts +++ /dev/null @@ -1,69 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { getPublicIpv4 } from "../../utils/getIp"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; - -export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), - { - modal: true, - stepName: 'postgresAddFirewallRule' - }, - { title: DialogResponses.yes.title } - ); - - await setFirewallRule(context, treeItem, ip); -} - -export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { - - const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); - const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); - const serverName: string = nonNullProp(treeItem, 'azureName'); - - const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip - }; - - const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); - }); - const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); -} - -export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); -} diff --git a/src/postgres/commands/connectPostgresDatabase.ts b/src/postgres/commands/connectPostgresDatabase.ts deleted file mode 100644 index 6996f7d03..000000000 --- a/src/postgres/commands/connectPostgresDatabase.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from 'vscode'; -import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from "../../extensionVariables"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; - -export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); - - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } -} diff --git a/src/postgres/commands/copyConnectionString.ts b/src/postgres/commands/copyConnectionString.ts deleted file mode 100644 index 716bbd5b6..000000000 --- a/src/postgres/commands/copyConnectionString.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; - -export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); - } else { - connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); - } - - await vscode.env.clipboard.writeText(connectionString); - const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); - void vscode.window.showInformationMessage(message); -} diff --git a/src/postgres/commands/createPostgresDatabase.ts b/src/postgres/commands/createPostgresDatabase.ts deleted file mode 100644 index 6c096a52b..000000000 --- a/src/postgres/commands/createPostgresDatabase.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -import { connectPostgresDatabase } from './connectPostgresDatabase'; - -export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); -} diff --git a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts deleted file mode 100644 index 81d54b9af..000000000 --- a/src/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ /dev/null @@ -1,12 +0,0 @@ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; - -export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; -} diff --git a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts deleted file mode 100644 index 27b32993c..000000000 --- a/src/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; - -export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { - returnType?: string; -} diff --git a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts deleted file mode 100644 index 8c4df098b..000000000 --- a/src/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, IActionContext } from "@microsoft/vscode-azext-utils"; -import { PostgresFunctionsTreeItem } from "../../../tree/PostgresFunctionsTreeItem"; -import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; -import { IPostgresFunctionQueryWizardContext } from "./IPostgresFunctionQueryWizardContext"; -import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; -import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; -import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; - -export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], - executeSteps: [new FunctionQueryCreateStep()], - title: 'Create PostgreSQL Function Query' - }); - - await runPostgresQueryWizard(wizard, wizardContext, treeItem); -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts deleted file mode 100644 index 9356882d9..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "../../../../../utils/nonNull"; -import { wrapArgInQuotes } from "../../../../runPostgresQuery"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IPostgresFunctionQueryWizardContext): Promise { - context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); - } - - public shouldExecute(): boolean { - return true; - } -} - -const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) - RETURNS ${returnType} - LANGUAGE plpgsql -AS $function$ - BEGIN - /* function body */ - END; -$function$ -`; diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts deleted file mode 100644 index cfacc0f64..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts deleted file mode 100644 index 36d798074..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { validateIdentifier } from "../../validateIdentifier"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; - -export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideFunctionName', 'Provide function name'), - validateInput: validateIdentifier - })).trim(); - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } -} diff --git a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts deleted file mode 100644 index 63f703793..000000000 --- a/src/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ /dev/null @@ -1,50 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; -import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; - -export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); - returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); - - context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize('selectReturnType', 'Select return type') - })).data; - } - - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } - - public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { - return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } -} - -// A subset of return types available on pgAdmin -const returnTypes: string[] = [ - 'bigint', - 'bigint[]', - 'boolean', - 'boolean[]', - 'character', - 'character[]', - 'date', - 'date[]', - 'integer', - 'integer[]', - 'json', - 'json[]', - 'oid', - 'oid[]', - 'smallint', - 'smallint[]', - 'text', - 'void' -]; diff --git a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts deleted file mode 100644 index 925695e56..000000000 --- a/src/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; -import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from '../../../utils/vscodeUtils'; -import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; -import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; -import { connectPostgresDatabase } from "../connectPostgresDatabase"; -import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; - -export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); - - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } -} diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts deleted file mode 100644 index f1ddbe51b..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, IActionContext } from "@microsoft/vscode-azext-utils"; -import { PostgresStoredProceduresTreeItem } from "../../../tree/PostgresStoredProceduresTreeItem"; -import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; -import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; -import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; - -export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: 'Create PostgreSQL Stored Procedure Query' - }); - - await runPostgresQueryWizard(wizard, context, treeItem); -} diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts deleted file mode 100644 index 2cf3ef916..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; -import { nonNullProp } from "../../../../../utils/nonNull"; -import { wrapArgInQuotes } from "../../../../runPostgresQuery"; -import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; - -export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; - - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); - } - - public shouldExecute(): boolean { - return true; - } -} - -const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) - LANGUAGE plpgsql -AS $$ - BEGIN - /* stored procedure body */ - END; -$$ -`; diff --git a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts deleted file mode 100644 index bf9a00392..000000000 --- a/src/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../../utils/localize"; -import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; -import { validateIdentifier } from "../../validateIdentifier"; - -export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), - validateInput: validateIdentifier - })).trim(); - } - - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } -} diff --git a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts b/src/postgres/commands/createPostgresQuery/validateIdentifier.ts deleted file mode 100644 index 9339f6796..000000000 --- a/src/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ /dev/null @@ -1,113 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { localize } from "../../../utils/localize"; - -export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); - - const min = 1; - const max = 63; - - if (identifier.length < min || identifier.length > max) { - return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } - - if (!identifier[0].match(/[a-z_]/i)) { - return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); - } - - if (identifier.match(/[^a-z_\d$]/i)) { - return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); - } - - if (reservedWords.has(identifier.toLowerCase())) { - return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); - } - - return undefined; -} - -// Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html -const reservedWords: Set = new Set([ - 'all', - 'analyse', - 'analyze', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'asymmetric', - 'both', - 'case', - 'cast', - 'check', - 'collate', - 'column', - 'constraint', - 'create', - 'current_catalog', - 'current_date', - 'current_role', - 'current_time', - 'current_timestamp', - 'current_user', - 'default', - 'deferrable', - 'desc', - 'distinct', - 'do', - 'else', - 'end', - 'except', - 'false', - 'fetch', - 'for', - 'foreign', - 'from', - 'grant', - 'group', - 'having', - 'in', - 'initially', - 'intersect', - 'into', - 'lateral', - 'leading', - 'limit', - 'localtime', - 'localtimestamp', - 'not', - 'null', - 'offset', - 'on', - 'only', - 'or', - 'order', - 'placing', - 'primary', - 'references', - 'returning', - 'select', - 'session_user', - 'some', - 'symmetric', - 'table', - 'then', - 'to', - 'trailing', - 'true', - 'union', - 'unique', - 'user', - 'using', - 'variadic', - 'when', - 'where', - 'window', - 'with' -]); diff --git a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts deleted file mode 100644 index 390c1cf42..000000000 --- a/src/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; - -export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; - - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts deleted file mode 100644 index 2f07d8203..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; - -export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize('confirmPW', 'Confirm your password'); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) - }); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } - - private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { - if (passphrase !== context.adminPassword) { - return localize('pwMatch', 'The passwords must match.'); - } - - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts deleted file mode 100644 index f73ce810d..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from "@azure/arm-postgresql"; -import * as FlexibleModels from "@azure/arm-postgresql-flexible"; -import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; -import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; - - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - - const locationName: string = (await LocationListStep.getLocation(context)).name; - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); - const newServerName = nonNullProp(context, 'newServerName'); - const password: string = nonNullProp(context, 'adminPassword'); - - return await callWithMaskHandling( - async () => { - const serverType = nonNullProp(context, 'serverType'); - const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); - - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, 'sku'), - administratorLogin: nonNullProp(context, 'shortUserName'), - administratorLoginPassword: password, - size: parseInt(size) - }; - - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); - context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); - context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, - password); - } - - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } - - - private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier - }, - } - } - - private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size - } - } - } - } - -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts deleted file mode 100644 index c48d40c37..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); - -export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, 'shortUserName'); - context.adminPassword = (await context.ui.showInputBox({ - placeHolder: localize('pwPlaceholder', 'Administrator Password'), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => validatePassword(user, password), - })); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } -} - -async function validatePassword(username: string, password: string): Promise { - password = password ? password : ''; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map(substring => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); - } else { - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts deleted file mode 100644 index 7b4890d07..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = (await context.ui.showInputBox({ - placeHolder: localize('usernamePlaceholder', 'Administrator Username'), - validateInput: validateUser, - })).trim(); - const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; - context.longUserName = context.shortUserName + usernameSuffix; - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } -} - -async function validateUser(username: string): Promise { - username = username ? username.trim() : ''; - - const min = 1; - const max = 63; - - const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; - - if (username.length < min || username.length > max) { - return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); - } else if (username.match(/^[0-9]+/)) { - return localize('usernameBeginningMatch', 'The name cannot start with a number.'); - } else if (username.toLowerCase().startsWith('pg_')) { - return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map(d => `"${d}"`).join(', '); - return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); - } else { - return undefined; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts deleted file mode 100644 index 1af03f5c7..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ /dev/null @@ -1,60 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; -import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerNameStep extends AzureNameStep { - - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: localize('serverNamePlaceholder', 'Server name'), - prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), - validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} - -async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { - name = name ? name.trim() : ''; - - const min = 3; - const max = 63; - - if (name.length < min || name.length > max) { - return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } else if (!(/^[a-z0-9-]+$/).test(name)) { - return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); - } else if (name.startsWith('-') || name.endsWith('-')) { - return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); - } - const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); - - if (!availability.nameAvailable) { - return availability.message ? - availability.message : - localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); - } - - return undefined; - -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts deleted file mode 100644 index 3431e8f00..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; -import { setPostgresCredentials } from '../../setPostgresCredentials'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; - -export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; - - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if (context.serverType && context.serverType === PostgresServerType.Single) { - user = nonNullProp(context, 'longUserName'); - } else { - user = nonNullProp(context, 'shortUserName'); - } - const newServerName: string = nonNullProp(context, 'newServerName'); - - const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, 'adminPassword'); - const server: PostgresAbstractServer = nonNullProp(context, 'server'); - - await setPostgresCredentials(user, password, nonNullProp(server, 'id')); - const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } - - public shouldExecute(): boolean { - return true; - } -} diff --git a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts deleted file mode 100644 index 654cd0430..000000000 --- a/src/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ /dev/null @@ -1,250 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; -import { localize } from "../../../../utils/localize"; -import { nonNullProp } from "../../../../utils/nonNull"; -import { openUrl } from "../../../../utils/openUrl"; -import { AbstractSku, PostgresServerType } from "../../../abstract/models"; -import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; - -interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; -} - -export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresServerWizardContext - ): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); - pricingTiers.push({ - label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), - onPicked: async () => { - await openUrl('https://aka.ms/AAcxhvm'); - }, data: undefined - }); - - context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } - - public async getPicks(serverType: PostgresServerType): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; - - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: option.group || localize('addlOptions', 'Additional Options') - }); - }); - return options; - } -} - -const recommendedGroup = localize('recommendGroup', 'Recommended'); -const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, -]; - -// Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 -// See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage -const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, -]; diff --git a/src/postgres/commands/deletePostgresDatabase.ts b/src/postgres/commands/deletePostgresDatabase.ts deleted file mode 100644 index a09520bde..000000000 --- a/src/postgres/commands/deletePostgresDatabase.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; - -export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); - const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresFunction.ts b/src/postgres/commands/deletePostgresFunction.ts deleted file mode 100644 index 9a4547428..000000000 --- a/src/postgres/commands/deletePostgresFunction.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; - -export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } - - const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresServer.ts b/src/postgres/commands/deletePostgresServer.ts deleted file mode 100644 index 733c6fca6..000000000 --- a/src/postgres/commands/deletePostgresServer.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; -import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; - -export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - await deleteDatabaseAccount(context, node, true) -} diff --git a/src/postgres/commands/deletePostgresStoredProcedure.ts b/src/postgres/commands/deletePostgresStoredProcedure.ts deleted file mode 100644 index 6abece79b..000000000 --- a/src/postgres/commands/deletePostgresStoredProcedure.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; - -export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } - - const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/deletePostgresTable.ts b/src/postgres/commands/deletePostgresTable.ts deleted file mode 100644 index bfdce33a2..000000000 --- a/src/postgres/commands/deletePostgresTable.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; - -export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); - await node.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); -} diff --git a/src/postgres/commands/enterPostgresCredentials.ts b/src/postgres/commands/enterPostgresCredentials.ts deleted file mode 100644 index aa993c337..000000000 --- a/src/postgres/commands/enterPostgresCredentials.ts +++ /dev/null @@ -1,85 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { PostgresServerType } from '../abstract/models'; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -import { setPostgresCredentials } from "./setPostgresCredentials"; - -/** - * Get the username and password for the Postgres database from user input. - */ -async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string, password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), - stepName: 'enterPostgresUsername', - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } - }); - - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { - username += usernameSuffix; - } - - const password: string = await context.ui.showInputBox({ - prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), - stepName: 'enterPostgresPassword', - password: true, - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } - }); - - return { username, password }; -} - -/** - * Save the username and password in secure local storage. - */ -async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { - const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); - - const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); -} - -export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, 'azureName'); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, 'id'); - - const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); - - await persistUsernamePassword(id, serverName, username, password); - - treeItem.setCredentials(username, password); - await treeItem.refresh(context); -} diff --git a/src/postgres/commands/executePostgresQueryInDocument.ts b/src/postgres/commands/executePostgresQueryInDocument.ts deleted file mode 100644 index af5d3ca5e..000000000 --- a/src/postgres/commands/executePostgresQueryInDocument.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { EOL } from 'os'; -import * as path from 'path'; -import { ClientConfig, QueryResult } from 'pg'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import * as vscodeUtil from '../../utils/vscodeUtils'; -import { runPostgresQuery } from '../runPostgresQuery'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; -import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; - -export async function executePostgresQueryInDocument(context: IActionContext): Promise { - await loadPersistedPostgresDatabase(); - - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - - const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); - - const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - - if (!activeEditor?.document) { - throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); - } - - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); - ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); - - if (queryResult.rowCount) { - const fileExtension: string = path.extname(activeEditor.document.fileName); - const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); - const outputFileName: string = `${queryFileName}-output`; - - const fields: string[] = queryResult.fields.map(f => f.name); - let csvData: string = `${fields.join(',')}${EOL}`; - - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(',')}${EOL}`; - } - - await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); - } - await treeItem.refresh(context); -} diff --git a/src/postgres/commands/openPostgresFunction.ts b/src/postgres/commands/openPostgresFunction.ts deleted file mode 100644 index 26103970f..000000000 --- a/src/postgres/commands/openPostgresFunction.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { showPostgresQuery } from "../showPostgresQuery"; -import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; - -export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } - - await showPostgresQuery(treeItem); -} diff --git a/src/postgres/commands/openPostgresStoredProcedure.ts b/src/postgres/commands/openPostgresStoredProcedure.ts deleted file mode 100644 index 3c98ff743..000000000 --- a/src/postgres/commands/openPostgresStoredProcedure.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { showPostgresQuery } from "../showPostgresQuery"; -import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; - -export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } - - await showPostgresQuery(treeItem); -} diff --git a/src/postgres/commands/registerPostgresCommands.ts b/src/postgres/commands/registerPostgresCommands.ts deleted file mode 100644 index b861e00f7..000000000 --- a/src/postgres/commands/registerPostgresCommands.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { defaults } from "pg"; -import { languages } from "vscode"; -import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; -import { ext } from "../../extensionVariables"; -import { openUrl } from "../../utils/openUrl"; -import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; -import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -import { configurePostgresFirewall } from "./configurePostgresFirewall"; -import { connectPostgresDatabase } from "./connectPostgresDatabase"; -import { copyConnectionString } from "./copyConnectionString"; -import { createPostgresDatabase } from "./createPostgresDatabase"; -import { createPostgresFunctionQuery } from "./createPostgresQuery/function/createPostgresFunctionQuery"; -import { createPostgresStoredProcedureQuery } from "./createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery"; -import { deletePostgresDatabase } from "./deletePostgresDatabase"; -import { deletePostgresFunction } from "./deletePostgresFunction"; -import { deletePostgresServer } from "./deletePostgresServer"; -import { deletePostgresStoredProcedure } from "./deletePostgresStoredProcedure"; -import { deletePostgresTable } from "./deletePostgresTable"; -import { enterPostgresCredentials } from "./enterPostgresCredentials"; -import { executePostgresQueryInDocument } from "./executePostgresQueryInDocument"; -import { openPostgresFunction } from "./openPostgresFunction"; -import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; - -export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); - - void loadPersistedPostgresDatabase(); - - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; - - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); - registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); - registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); - registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); - registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); - registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); -} - -export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); - if (persistedTreeItem) { - await connectPostgresDatabase(context, persistedTreeItem); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); -} - -export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); -} diff --git a/src/postgres/commands/setPostgresCredentials.ts b/src/postgres/commands/setPostgresCredentials.ts deleted file mode 100644 index 8df8260f6..000000000 --- a/src/postgres/commands/setPostgresCredentials.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from "../../extensionVariables"; -import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; -import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; - -interface IPersistedServer { - id: string; - username: string; -} - -export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); - - const newServer: IPersistedServer = { - id: serverId, - username - }; - - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); -} diff --git a/src/postgres/getClientConfig.ts b/src/postgres/getClientConfig.ts deleted file mode 100644 index bdc545945..000000000 --- a/src/postgres/getClientConfig.ts +++ /dev/null @@ -1,172 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Client, ClientConfig } from "pg"; -import { ConnectionOptions } from "tls"; -import { postgresDefaultPort } from "../constants"; -import { nonNullProp } from "../utils/nonNull"; -import { PostgresServerType } from "./abstract/models"; -import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; - -export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; -}; -export type PostgresClientConfigType = keyof PostgresClientConfigs; - -/** - * Test if the database can be connected to using the given client config. - * @throws if the client failed to connect to the database. - */ -export async function testClientConfig(clientConfig: ClientConfig): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } -} - -async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString(connectionString, databaseName); - } - return { connectionString: connectionString }; -} - -async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; - - if (!!username && !!password && !!host && !!port) { - return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; - } else { - return undefined; - } -} - -async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise -): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; -} - -export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise -): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] - }; - const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { - const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); - clientConfigs.connectionString = connectionStringClientConfig; - } - - return clientConfigs; -} - -// Postgres Single Server Root Cert, https://aka.ms/AA7wnvl -export const BaltimoreCyberTrustRoot: string = `-----BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE-----`; - -// Postgres Single Server Root Cert will be updated to DigiCertGlobalRootG2, https://aka.ms/AA7wnvl -export const DigiCertGlobalRootG2: string = `-----BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE-----`; - -// Postgres Flexible Server Root Cert, https://aka.ms/AAd75x5 -export const DigiCertGlobalRootCA: string = `-----BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE-----`; - diff --git a/src/postgres/getPostgresProcedureQueryRows.ts b/src/postgres/getPostgresProcedureQueryRows.ts deleted file mode 100644 index ad791ff2e..000000000 --- a/src/postgres/getPostgresProcedureQueryRows.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { QueryResult } from "pg"; -import { runPostgresQuery } from "./runPostgresQuery"; -import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; -import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; - -export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; -} - -function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, - p.proname as name, - p.oid as oid, - pg_get_function_arguments(p.oid) as args, - case when l.lanname = 'internal' then p.prosrc - else pg_get_functiondef(p.oid) - end as definition - from pg_proc p - left join pg_namespace n on p.pronamespace = n.oid - left join pg_language l on p.prolang = l.oid - where n.nspname not in ('pg_catalog', 'information_schema') - ${conditions} - order by name;`; -} - -export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { - let conditions: string; - - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } - - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } - - return rows; -} diff --git a/src/postgres/getTables.ts b/src/postgres/getTables.ts deleted file mode 100644 index ebc7d1c75..000000000 --- a/src/postgres/getTables.ts +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ClientConfig, QueryResult } from "pg"; -import { runPostgresQuery } from "./runPostgresQuery"; - -export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; -} - -const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, - concat('"', schemaname, '"."', tablename, '"')::regclass::oid as oid - from pg_catalog.pg_tables - left join ( - select column_name::text as columnname, table_name, table_schema - from information_schema.columns - ) columns on table_name = tablename and table_schema = schemaname - where schemaname != 'pg_catalog' AND schemaname != 'information_schema' - group by schemaname, tablename;`; - -export async function getTables(clientConfig: ClientConfig): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); - } - return tablesArray; -} diff --git a/src/postgres/postgresConnectionStrings.ts b/src/postgres/postgresConnectionStrings.ts deleted file mode 100644 index ea9ce9e2e..000000000 --- a/src/postgres/postgresConnectionStrings.ts +++ /dev/null @@ -1,74 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConnectionOptions, parse } from "pg-connection-string"; -import { postgresDefaultPort } from "../constants"; -import { ParsedConnectionString } from "../ParsedConnectionString"; -import { nonNullProp } from "../utils/nonNull"; - -export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); -} - -export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); -} - -export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; -} - -export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; -} - -export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; - - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, 'host'); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } -} diff --git a/src/postgres/postgresConstants.ts b/src/postgres/postgresConstants.ts deleted file mode 100644 index 9bcf15144..000000000 --- a/src/postgres/postgresConstants.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export const invalidCredentialsErrorType: string = '28P01'; -export const firewallNotConfiguredErrorType: string = '28000'; -export const timeoutErrorType = 'ETIMEDOUT'; diff --git a/src/postgres/runPostgresQuery.ts b/src/postgres/runPostgresQuery.ts deleted file mode 100644 index b7d325364..000000000 --- a/src/postgres/runPostgresQuery.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Client, ClientConfig, QueryResult } from "pg"; - -export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } -} -export function wrapArgInQuotes(input: string): string { - return `"${input}"`; -} diff --git a/src/postgres/services/PostgresCodeLensProvider.ts b/src/postgres/services/PostgresCodeLensProvider.ts deleted file mode 100644 index 5d075eb3c..000000000 --- a/src/postgres/services/PostgresCodeLensProvider.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; -import { localize } from "../../utils/localize"; - -export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; - - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } - - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } - - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; - - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; - - let title: string; - if (!isInitialized) { - title = localize('initializing', 'Initializing...'); - } else if (isConnected) { - title = localize('connectedToDatabase', 'Connected to "{0}"', database); - } else { - title = localize('connectToDatabase', 'Connect to a database'); - } - - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && 'postgreSQL.connectDatabase' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - - if (isConnected) { - lenses.push({ - command: { - title: 'Execute Query', - command: 'postgreSQL.executeQuery' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - } - - return lenses; - }); - } -} diff --git a/src/postgres/showPostgresQuery.ts b/src/postgres/showPostgresQuery.ts deleted file mode 100644 index 7d6e2aa1d..000000000 --- a/src/postgres/showPostgresQuery.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { postgresBaseFileName, postgresFileExtension } from '../constants'; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; -import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; - -export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); -} diff --git a/src/postgres/tree/ClientConfigFactory.ts b/src/postgres/tree/ClientConfigFactory.ts deleted file mode 100644 index 271f5b92f..000000000 --- a/src/postgres/tree/ClientConfigFactory.ts +++ /dev/null @@ -1,86 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; -import { localize } from "../../utils/localize"; -import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; -import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; - -export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; - -/** - * Creates an object that can be used to execute a postgres query with connection test and telemetry. - */ -export class PostgresClientConfigFactory { - public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ - type: "azureAd" | "password" | "connectionString", - clientConfig: ClientConfig - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); - - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); - - const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; - - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } - - try { - await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = clientConfigType; - await testClientConfig(clientConfig); - }); - return { - type: clientConfigType, - clientConfig - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), - code: firewallNotConfiguredErrorType - }; - } else { - throw error; - } - } - } - - throw { - message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), - code: invalidCredentialsErrorType - }; - } -} diff --git a/src/postgres/tree/PostgresColumnTreeItem.ts b/src/postgres/tree/PostgresColumnTreeItem.ts deleted file mode 100644 index d284c8122..000000000 --- a/src/postgres/tree/PostgresColumnTreeItem.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; - -export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; - - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } - - public get id(): string { - return this.columnName; - } - - public get label(): string { - return this.columnName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('split-horizontal'); - } - -} diff --git a/src/postgres/tree/PostgresDatabaseTreeItem.ts b/src/postgres/tree/PostgresDatabaseTreeItem.ts deleted file mode 100644 index 05f7a4412..000000000 --- a/src/postgres/tree/PostgresDatabaseTreeItem.ts +++ /dev/null @@ -1,115 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// eslint-disable-next-line import/no-internal-modules -import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { ThemeIcon } from 'vscode'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresServerTreeItem } from './PostgresServerTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; - - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresFirewall', - label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.configureFirewall' - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } - - try { - const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig) - ]; - - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); - } - - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); - - if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresCredentials', - label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.enterCredentials' - }); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - return []; - } else { - throw error; - } - } - } - - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); - } - - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); - await this.refresh(context); - } -} diff --git a/src/postgres/tree/PostgresFunctionTreeItem.ts b/src/postgres/tree/PostgresFunctionTreeItem.ts deleted file mode 100644 index 0a26bf3f9..000000000 --- a/src/postgres/tree/PostgresFunctionTreeItem.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { IPostgresProceduresQueryRow } from "../getPostgresProcedureQueryRows"; -import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; -import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; - -export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresFunction'; - public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; - - constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openFunction'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } - - public get label(): string { - return this.name; - } - - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); - } -} diff --git a/src/postgres/tree/PostgresFunctionsTreeItem.ts b/src/postgres/tree/PostgresFunctionsTreeItem.ts deleted file mode 100644 index 7d3904e83..000000000 --- a/src/postgres/tree/PostgresFunctionsTreeItem.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; - -export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresFunctions'; - public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; - public readonly label: string = 'Functions'; - public readonly childTypeLabel: string = 'Function'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } -} diff --git a/src/postgres/tree/PostgresResourcesTreeItemBase.ts b/src/postgres/tree/PostgresResourcesTreeItemBase.ts deleted file mode 100644 index b93cc9450..000000000 --- a/src/postgres/tree/PostgresResourcesTreeItemBase.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; - -// Base class for Postgres tree items whose children are individual resources -export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } - - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } -} diff --git a/src/postgres/tree/PostgresServerTreeItem.ts b/src/postgres/tree/PostgresServerTreeItem.ts deleted file mode 100644 index 20e7dbe76..000000000 --- a/src/postgres/tree/PostgresServerTreeItem.ts +++ /dev/null @@ -1,252 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as SingleModels from '@azure/arm-postgresql'; -import * as FlexibleModels from '@azure/arm-postgresql-flexible'; -import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import { ClientConfig } from 'pg'; -import { SemVer, coerce, gte } from 'semver'; -import * as vscode from 'vscode'; -import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { isIpInRanges } from '../../utils/getIp'; -import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; -import { getPublicIp } from '../commands/configurePostgresFirewall'; -import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -interface IPersistedServer { - id: string; - username: string; -} - -export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; - } - this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('PostgresServer.svg'); - } - - public get label(): string { - return this.azureName ? this.azureName : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); - dbNames = listOfDatabases.map(db => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map(db => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - 'invalidPostgresServer', - dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, - dbName => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); - } - const getChildrenTask: Promise = this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createPostgresDatabase', - validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) - }); - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, '11.0.0'); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); - - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); - } - - public async getFullConnectionString(): Promise { - - if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { - const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp(this, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); - const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } -} - -async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { - if (!name) { - return localize('NameCannotBeEmpty', 'Name cannot be empty.'); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize('NameExists', 'Database "{0}" already exists.', name); - } - return undefined; -} diff --git a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts b/src/postgres/tree/PostgresStoredProcedureTreeItem.ts deleted file mode 100644 index 503d0ae74..000000000 --- a/src/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ThemeIcon } from "vscode"; -import { IPostgresProceduresQueryRow } from "../getPostgresProcedureQueryRows"; -import { runPostgresQuery } from "../runPostgresQuery"; -import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; - -export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresStoredProcedure'; - public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; - - constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openStoredProcedure'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } - - public get label(): string { - return this.name; - } - - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); - } -} diff --git a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts b/src/postgres/tree/PostgresStoredProceduresTreeItem.ts deleted file mode 100644 index 1c516e00f..000000000 --- a/src/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; - -export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresStoredProcedures'; - public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = 'Stored Procedures'; - public readonly childTypeLabel: string = 'Stored Procedure'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } -} diff --git a/src/postgres/tree/PostgresTableTreeItem.ts b/src/postgres/tree/PostgresTableTreeItem.ts deleted file mode 100644 index ef5d87c2c..000000000 --- a/src/postgres/tree/PostgresTableTreeItem.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IPostgresTable } from '../getTables'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; - -export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; - - private _isDuplicate: boolean; - - constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } - - public get id(): string { - return String(this.table.oid); - } - - public get label(): string { - return this.table.name; - } - - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); - } - -} diff --git a/src/postgres/tree/PostgresTablesTreeItem.ts b/src/postgres/tree/PostgresTablesTreeItem.ts deleted file mode 100644 index c18c065db..000000000 --- a/src/postgres/tree/PostgresTablesTreeItem.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from "pg"; -import { ThemeIcon } from 'vscode'; -import { getTables, IPostgresTable } from "../getTables"; -import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; -import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; -import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; - -export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = 'Tables'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); - } - return tables.map(table => new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } -} diff --git a/src/resolver/AppResolver.ts b/src/resolver/AppResolver.ts deleted file mode 100644 index 0f75cdf29..000000000 --- a/src/resolver/AppResolver.ts +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; -import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; -import { tryGetExperience } from "../AzureDBExperiences"; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from "../extensionVariables"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { PostgresAbstractServer } from "../postgres/abstract/models"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; -import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; -import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; - -const resourceTypes = [ - 'microsoft.documentdb/databaseaccounts', - 'microsoft.dbforpostgresql/servers', - 'microsoft.dbforpostgresql/flexibleservers' -]; - -export class DatabaseResolver implements AppResourceResolver { - public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { - return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); - try { - const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); - const name = nonNullProp(resource, 'name'); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; - - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ ...context, ...subContext }); - const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); - const experience = tryGetExperience(databaseAccount); - - return experience?.api === 'MongoDB' ? - new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : - new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? - await createPostgreSQLClient({ ...context, ...subContext }) : - await createPostgreSQLFlexibleClient({ ...context, ...subContext }); - - postgresServer = await postgresClient.servers.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); - - return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - }); - } - - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } -} diff --git a/src/resolver/DatabaseWorkspaceProvider.ts b/src/resolver/DatabaseWorkspaceProvider.ts deleted file mode 100644 index 14e50d643..000000000 --- a/src/resolver/DatabaseWorkspaceProvider.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; -import { Disposable } from "vscode"; -import { ext } from "../extensionVariables"; -import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; - - -export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise { - - return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - }); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } -} - diff --git a/src/resolver/ResolvedDatabaseAccountResource.ts b/src/resolver/ResolvedDatabaseAccountResource.ts deleted file mode 100644 index 0222dded7..000000000 --- a/src/resolver/ResolvedDatabaseAccountResource.ts +++ /dev/null @@ -1,57 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; - -export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue) - this.maskedValuestoAdd.push(...ti.valuesToMask); - } -} diff --git a/src/resolver/ResolvedDocDBAccountResource.ts b/src/resolver/ResolvedDocDBAccountResource.ts deleted file mode 100644 index cf1bfc4bc..000000000 --- a/src/resolver/ResolvedDocDBAccountResource.ts +++ /dev/null @@ -1,32 +0,0 @@ - - -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; -import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; -import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } -} diff --git a/src/resolver/ResolvedMongoAccountResource.ts b/src/resolver/ResolvedMongoAccountResource.ts deleted file mode 100644 index 4f45486ef..000000000 --- a/src/resolver/ResolvedMongoAccountResource.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; -import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - root: IMongoTreeRoot; - - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - } -} diff --git a/src/resolver/ResolvedPostgresServerResource.ts b/src/resolver/ResolvedPostgresServerResource.ts deleted file mode 100644 index a1e35acf3..000000000 --- a/src/resolver/ResolvedPostgresServerResource.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; -import { ClientConfig } from "pg"; -import { PostgresServerType } from "../postgres/abstract/models"; -import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; -import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; - -export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise - deletePostgresCredentials: () => Promise - getFullConnectionString: () => Promise - validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise - isFirewallRuleSet: (context: IActionContext) => Promise - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } -} diff --git a/src/table/tree/TableAccountTreeItem.ts b/src/table/tree/TableAccountTreeItem.ts deleted file mode 100644 index 0d3b86e38..000000000 --- a/src/table/tree/TableAccountTreeItem.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; -import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; - -export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public initChild(): AzExtTreeItem { - throw new Error('Table Accounts are not supported yet.'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'tableNotSupported', - label: 'Table Accounts are not supported yet.' - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } - - public isAncestorOfImpl(): boolean { - return false; - } -} diff --git a/src/tree/AttachedAccountsTreeItem.ts b/src/tree/AttachedAccountsTreeItem.ts deleted file mode 100644 index d854e506f..000000000 --- a/src/tree/AttachedAccountsTreeItem.ts +++ /dev/null @@ -1,420 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { removeTreeItemFromCache } from '../commands/api/apiCache'; -import { emulatorPassword, isWindows } from '../constants'; -import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; -import { connectToMongoClient } from '../mongo/connectToMongoClient'; -import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; -import { getSecretStorageKey } from '../utils/getSecretStorageKey'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; - -interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; -} - -export const AttachedAccountSuffix: string = 'Attached'; -export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; - -const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; - -export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); - public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; - public readonly label: string = 'Attached Database Accounts'; - public childTypeLabel: string = 'Account'; - public suppressMaskLabel = true; - - private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = 'cosmosDBAttachedAccounts'; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('plug'); - } - - public static validateMongoConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); - } - - private static validateDocDBConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachDatabaseAccount', - label: 'Attach Database Account...', - commandId: 'cosmosDB.attachDatabaseAccount', - includeInTreeItemPicker: true - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachEmulator', - label: 'Attach Emulator...', - commandId: 'cosmosDB.attachEmulator', - includeInTreeItemPicker: true - }); - return isWindows ? [attachDatabaseAccount, attachEmulator] : - [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = 'mongodb://host:port'; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; - } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { - placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); - validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = 'AccountEndpoint=...;AccountKey=...'; - validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = (await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: 'Enter the connection string for your database account', - stepName: 'attachNewAccountConnectionString', - validateInput: validateInput, - value: defaultValue - })).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { - const treeItem = await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core) - ], - { - placeHolder: "Select a Database Account API...", - stepName: 'attachEmulator' - }); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); - if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.find(s => s.id === treeItem.id)) { - void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get(this._serviceName); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all(accounts.map(async account => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof (account) === 'string') { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${getExperienceFromApi(api).shortName})`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); - persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); - })); - } - - return persistedAccounts; - } - - private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error(`Unexpected account node "${node.constructor.name}".`); - } - return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; - }); - await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); - } -} - -class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); - - public get credentials(): never { - throw this._error; - } - - public get subscriptionDisplayName(): never { - throw this._error; - } - - public get subscriptionId(): never { - throw this._error; - } - - public get subscriptionPath(): never { - throw this._error; - } - - public get tenantId(): never { - throw this._error; - } - - public get userId(): never { - throw this._error; - } - - public get environment(): never { - throw this._error; - } - - public get isCustomCloud(): never { - throw this._error; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} diff --git a/src/tree/AzureAccountTreeItemWithAttached.ts b/src/tree/AzureAccountTreeItemWithAttached.ts deleted file mode 100644 index 172cd598f..000000000 --- a/src/tree/AzureAccountTreeItemWithAttached.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; -import { ext } from '../extensionVariables'; -import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; - -export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } - - public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } - - public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); - return children.concat(ext.attachedAccountsNode); - } - - public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } -} diff --git a/src/tree/AzureDBAPIStep.ts b/src/tree/AzureDBAPIStep.ts deleted file mode 100644 index 8a11fdc95..000000000 --- a/src/tree/AzureDBAPIStep.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; -import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; -import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; -import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; -import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; -import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; -import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; -import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; -import { localize } from '../utils/localize'; -import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; -import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; -import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; -import { IAzureDBWizardContext } from './IAzureDBWizardContext'; - -export class AzureDBAPIStep extends AzureWizardPromptStep { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); - - const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { - placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') - }); - - context.defaultExperience = result.data; - } - - public async getSubWizard(context: IAzureDBWizardContext): Promise> { - let promptSteps: AzureWizardPromptStep[]; - let executeSteps: AzureWizardExecuteStep[]; - if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(['Microsoft.DocumentDB']) - ]; - } - return { promptSteps, executeSteps }; - } - - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts deleted file mode 100644 index b46453e3a..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { - - public async prompt(context: ICosmosDBWizardContext): Promise { - - const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') - const picks: IAzureQuickPickItem[] = [ - { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, - { label: localize('serverlessOption', 'Serverless'), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; - - do { - pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); - if (pick === learnMore) { - await openUrl('https://aka.ms/cosmos-models'); - } - } while (pick === learnMore); - - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; - } - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts deleted file mode 100644 index 4bd469b84..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ /dev/null @@ -1,63 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; -import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { Progress } from 'vscode'; -import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const locationName: string = (await LocationListStep.getLocation(context)).name; - const defaultExperience = nonNullProp(context, 'defaultExperience'); - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const accountName = nonNullProp(context, 'newServerName'); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: 'Standard', - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, - }; - - if (defaultExperience?.api === 'MongoDB') { - options.apiProperties = { serverVersion: '3.6' }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } -} diff --git a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts deleted file mode 100644 index 87ef6be61..000000000 --- a/src/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; - -export class CosmosDBAccountNameStep extends AzureNameStep { - - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => validateCosmosDBAccountName(name, client) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} - -async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { - name = name ? name.trim() : ''; - - const min = 3; - const max = 31; - - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } -} diff --git a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts deleted file mode 100644 index 61666a859..000000000 --- a/src/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; - -export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; - -} diff --git a/src/tree/IAzureDBWizardContext.ts b/src/tree/IAzureDBWizardContext.ts deleted file mode 100644 index fd84ff0d5..000000000 --- a/src/tree/IAzureDBWizardContext.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { Experience } from '../AzureDBExperiences'; - -export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - - newServerName?: string; - defaultExperience?: Experience; - -} diff --git a/src/tree/SubscriptionTreeItem.ts b/src/tree/SubscriptionTreeItem.ts deleted file mode 100644 index 910d8d970..000000000 --- a/src/tree/SubscriptionTreeItem.ts +++ /dev/null @@ -1,158 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; -import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; -import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from '../extensionVariables'; -import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; -import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from '../utils/activityUtils'; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { localize } from '../utils/localize'; -import { nonNullProp } from '../utils/nonNull'; -import { AzureDBAPIStep } from './AzureDBAPIStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; - -export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = 'Account'; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - - //Postgres - const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); - const postgresServers: PostgresAbstractServer[] = [ - ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), - ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), - ]; - - const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - postgresServers, - 'invalidPostgreSQLAccount', - async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); - const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - accounts, - 'invalidCosmosDBAccount', - async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep() - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize('createDBServerMsg', 'Create new Azure Database Server') - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp(wizardContext, 'newServerName'); - wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { - const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, 'server'); - const host = nonNullProp(server, 'fullyQualifiedDomainName'); - const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); - const password: string = nonNullProp(wizardContext, 'adminPassword'); - const connectionString: string = createPostgresConnectionString(host, undefined, username, password); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return typeof contextValue !== 'string' || !/attached/i.test(contextValue); - } - - public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, 'id'); - const name: string = nonNullProp(databaseAccount, 'name'); - const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); - const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = 'retrywrites'; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, 'false'); - } - - // Use the default connection string - return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); - } else { - const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - case "Graph": { - const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); - return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - - } - } - } - public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { - const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } -} diff --git a/src/utils/InteractiveChildProcess.ts b/src/utils/InteractiveChildProcess.ts deleted file mode 100644 index 26129b342..000000000 --- a/src/utils/InteractiveChildProcess.ts +++ /dev/null @@ -1,176 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as cp from 'child_process'; -import * as os from 'os'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { Event, EventEmitter } from 'vscode'; -import { improveError } from './improveError'; - -// We add these when we display to the output window -const stdInPrefix = '> '; -const stdErrPrefix = 'ERR> '; -const errorPrefix = 'Error running process: '; - -const processStartupTimeout = 60; - -export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; -} - -export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create(options: IInteractiveChildProcessOptions): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess(options); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(' '); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false - }; - - this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); - this._childProc = cp.spawn(this._options.command, this._options.args, options); - - this._childProc.stdout?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on('error', (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on('close', (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel(text: string, displayPrefix?: string): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = (filteredText !== text && filteredText === ''); - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); - } - - return text; - } -} - -async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); -} diff --git a/src/utils/activityUtils.ts b/src/utils/activityUtils.ts deleted file mode 100644 index fefd2fe00..000000000 --- a/src/utils/activityUtils.ts +++ /dev/null @@ -1,15 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -import { ext } from "../extensionVariables"; -import { getWorkspaceSetting } from "./settingUtils"; - -export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), - }; -} diff --git a/src/utils/array.ts b/src/utils/array.ts deleted file mode 100644 index 06f095e8d..000000000 --- a/src/utils/array.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { - return arr ? arr.filter(element => element instanceof genericConstructor) : []; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { - return arr && arr.find(element => element instanceof genericConstructor); -} diff --git a/src/utils/azureClients.ts b/src/utils/azureClients.ts deleted file mode 100644 index 9be19e959..000000000 --- a/src/utils/azureClients.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; -import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; - -// Lazy-load @azure packages to improve startup performance. -// NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript - -export async function createCosmosDBClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); -} - -export async function createPostgreSQLClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); -} - -export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); -} diff --git a/src/utils/azureUtils.ts b/src/utils/azureUtils.ts deleted file mode 100644 index b0017314b..000000000 --- a/src/utils/azureUtils.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); - - if (!matches || matches.length < 5) { - throw new Error('Invalid Azure Resource Id'); - } - - return matches[4]; -} diff --git a/src/utils/cp.ts b/src/utils/cp.ts deleted file mode 100644 index 660dc3068..000000000 --- a/src/utils/cp.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as cp from 'child_process'; - -export async function commandSucceeds(command: string, ...args: string[]): Promise { - return await new Promise(resolve => { - cp.spawn(command, args) - .on('error', _error => resolve(false)) - .on('exit', code => resolve(code === 0)); - }); -} diff --git a/src/utils/getIp.ts b/src/utils/getIp.ts deleted file mode 100644 index 20d22e989..000000000 --- a/src/utils/getIp.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { isIPv4 } from 'net'; -import { localize } from './localize'; - -export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); -} - -export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, 'https://api.ipify.org/'), - () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; -} - -const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); - -function ipToNum(ip: string) { - return Number( - ip.split(".") - .map(d => ("000" + d).substring(-3)) - .join("") - ); -} - -async function getPublicIpv4Https(context: IActionContext, url: string): Promise { - const req = await sendRequestWithTimeout(context, { - method: 'GET', - url, - }, 5000, undefined); - - const ip = req.bodyAsText; - - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } - - return ip; -} diff --git a/src/utils/getSecretStorageKey.ts b/src/utils/getSecretStorageKey.ts deleted file mode 100644 index 80e116737..000000000 --- a/src/utils/getSecretStorageKey.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; -} diff --git a/src/utils/improveError.ts b/src/utils/improveError.ts deleted file mode 100644 index 27ff1f014..000000000 --- a/src/utils/improveError.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from "@microsoft/vscode-azext-utils"; - -export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } - - return error; -} diff --git a/src/utils/localize.ts b/src/utils/localize.ts deleted file mode 100644 index 2aee3fa12..000000000 --- a/src/utils/localize.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vscode-nls'; - -export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/src/utils/nonNull.ts b/src/utils/nonNull.ts deleted file mode 100644 index d7104b4f8..000000000 --- a/src/utils/nonNull.ts +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { isNullOrUndefined } from 'util'; - -/** - * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed - * for the property and will give a compile error if the given name is not a property of the source. - */ -export function nonNullProp(source: TSource, name: TKey): NonNullable { - const value: NonNullable = >source[name]; - return nonNullValue(value, name); -} - -/** - * Validates that a given value is not null and not undefined. - */ -export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { - if (isNullOrUndefined(value)) { - throw new Error( - 'Internal error: Expected value to be neither null nor undefined' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } - - return value; -} - -/** - * Validates that a given string is not null, undefined, nor empty - */ -export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { - if (!value) { - throw new Error( - 'Internal error: Expected value to be neither null, undefined, nor empty' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } - - return value; -} diff --git a/src/utils/openUrl.ts b/src/utils/openUrl.ts deleted file mode 100644 index 0be3f5bbb..000000000 --- a/src/utils/openUrl.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as open from 'open'; - -export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); - - await open(url); -} diff --git a/src/utils/randomUtils.ts b/src/utils/randomUtils.ts deleted file mode 100644 index 7a313f23a..000000000 --- a/src/utils/randomUtils.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as crypto from "crypto"; - -export namespace randomUtils { - export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { - return crypto.createHash('sha256').update(s).digest(encoding); - } - - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString('hex').slice(0, length); - } -} diff --git a/src/utils/settingUtils.ts b/src/utils/settingUtils.ts deleted file mode 100644 index 0ac1004c2..000000000 --- a/src/utils/settingUtils.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; -import { ext } from "../extensionVariables"; - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - await projectConfiguration.update(section, value, ConfigurationTarget.Global); -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); - return result && result.globalValue; -} - -/** - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); - return projectConfiguration.get(key); -} - -/** - * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) - * Uses ext.prefix 'azureDatabases' unless otherwise specified - */ -export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } -} diff --git a/src/utils/timeout.ts b/src/utils/timeout.ts deleted file mode 100644 index cc5ffb2d6..000000000 --- a/src/utils/timeout.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -const timedOutMessage = "Execution timed out"; - -/** - * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. - */ -export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } - - throw err; - } -} - -/** - * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. - */ -export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout( - () => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, - timeoutMs); - - let value: T; - let error; - - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); -} diff --git a/src/utils/vscodeUtils.ts b/src/utils/vscodeUtils.ts deleted file mode 100644 index d05f84872..000000000 --- a/src/utils/vscodeUtils.ts +++ /dev/null @@ -1,103 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ItemDefinition } from '@azure/cosmos'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; -import { getRootPath } from './workspacUtils'; - -export interface IDisposable { - dispose(): void; -} - -export function dispose(disposables: T[]): T[] { - disposables.forEach(d => d.dispose()); - return []; -} - -export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; -} - -export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); - const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); - await writeToEditor(editor, data); -} - -export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt(editor.document.lineCount - 1); - editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); - } - - editBuilder.insert(new vscode.Position(0, 0), data); - }); -} - -async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { - let count: number = 1; - const maxCount: number = 1024; - - while (count < maxCount) { - const fileSuffix = count === 0 ? '' : '-' + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; - - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } - - throw new Error('Could not find unique name for new file.'); -} - -export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join('/'); -} - -function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); -} - -export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== 'object') { - return String(value); - } - } - } - return String(document._id); -} - -function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; -} diff --git a/src/utils/workspacUtils.ts b/src/utils/workspacUtils.ts deleted file mode 100644 index 20b60da11..000000000 --- a/src/utils/workspacUtils.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { nonNullValue } from './nonNull'; - -export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; -} - -export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); -} diff --git a/src/utils/wrapError.ts b/src/utils/wrapError.ts deleted file mode 100644 index f6ec5d2b5..000000000 --- a/src/utils/wrapError.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; - -export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } - - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } - - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); -} diff --git a/src/vscode-cosmosdb.api.d.ts b/src/vscode-cosmosdb.api.d.ts deleted file mode 100644 index d5e4416c1..000000000 --- a/src/vscode-cosmosdb.api.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem(query: TreeItemQuery): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; -} - -export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; -} - -export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - } - - docDBData?: { - masterKey: string; - documentEndpoint: string; - } - - postgresData?: { - username: string | undefined; - password: string | undefined; - } - -} - -export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; -} - -export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; - -export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; - -export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; -} - -export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - } -} diff --git a/src/vscode-cosmosdbgraph.api.d.ts b/src/vscode-cosmosdbgraph.api.d.ts deleted file mode 100644 index 95cde2531..000000000 --- a/src/vscode-cosmosdbgraph.api.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export interface CosmosDBGraphExtensionApi { - apiVersion: string; - - openGraphExplorer(config: IGraphConfiguration): Promise; -} - -export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; -} - -export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; - - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; - - key: string; - databaseName: string; - graphName: string; - tabTitle: string; -} diff --git a/test/.eslintrc.js b/test/.eslintrc.js deleted file mode 100644 index afff31b69..000000000 --- a/test/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - "extends": [ - "@microsoft/eslint-config-azuretools", - "@microsoft/eslint-config-azuretools/test" - ] -}; diff --git a/test/attachedAccountsTreeItem.test.ts b/test/attachedAccountsTreeItem.test.ts deleted file mode 100644 index be76cad51..000000000 --- a/test/attachedAccountsTreeItem.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { AttachedAccountsTreeItem, MONGO_CONNECTION_EXPECTED } from '../extension.bundle'; - -function assertConnectionValid(connectionString: string, expected: string | undefined): void { - const actual = AttachedAccountsTreeItem.validateMongoConnectionString(connectionString); - assert.equal(actual, expected); -} - -suite(`attachedAccountsTreeItem`, () => { - suite(`validateDocDBConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - test('allows "mongodb://"', () => assertConnectionValid(`mongodb://your-mongo.documents.azure.com:10255`, undefined)); - - test('allows "mongodb+srv://"', () => assertConnectionValid(`mongodb+srv://usr:pwd@mongodb.net:27017`, undefined)); - - test('rejects bad prefix', () => assertConnectionValid(`http://localhost/`, MONGO_CONNECTION_EXPECTED)); - - test('rejects null', () => assertConnectionValid(null!, MONGO_CONNECTION_EXPECTED)); - }); -}); diff --git a/test/docDBConnectionStrings.test.ts b/test/docDBConnectionStrings.test.ts deleted file mode 100644 index e04c0a96f..000000000 --- a/test/docDBConnectionStrings.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { emulatorPassword, parseDocDBConnectionString } from '../extension.bundle'; - -function testConnectionString(connectionString: string, expectedEndpoint: string, expectedKey: string, expectedDatabaseName: string | undefined): void { - const parsedCS = parseDocDBConnectionString(connectionString); - assert.equal(parsedCS.documentEndpoint, expectedEndpoint); - assert.equal(parsedCS.masterKey, expectedKey); - assert.equal(parsedCS.databaseName, expectedDatabaseName); -} - -suite(`docDBConnectionStrings`, () => { - test(`Without database name`, () => { - // Testing different ordering, different use of ';', different casing, etc. - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString(' AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/; AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('accountendpoint=https://abcdef.documents.azure.com:443/;accountkey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - testConnectionString('AccountKey=abcdef==;AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', undefined); - - // emulator - testConnectionString(`AccountEndpoint=https://localhost:10255/;AccountKey=${emulatorPassword};`, 'https://localhost:10255/', emulatorPassword, undefined); - - // Testing other properties - const parsedCS = parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;'); - assert.equal(parsedCS.hostName, 'abcdef.documents.azure.com'); - assert.equal(parsedCS.port, '443'); - assert.equal(parsedCS.accountId, 'abcdef.documents.azure.com:443'); - assert.equal(parsedCS.fullId, 'abcdef.documents.azure.com:443'); - }); - - test(`With database name`, () => { - // Testing different ordering, different use of ';', different casing, etc. - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;Database=abcd;AccountKey=abcdef==', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - testConnectionString('Database=abcd;AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;', 'https://abcdef.documents.azure.com:443/', 'abcdef==', 'abcd'); - - // Testing other properties - const parsedCS = parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/;AccountKey=abcdef==;Database=abcd'); - assert.equal(parsedCS.hostName, 'abcdef.documents.azure.com'); - assert.equal(parsedCS.port, '443'); - assert.equal(parsedCS.accountId, 'abcdef.documents.azure.com:443'); - assert.equal(parsedCS.fullId, 'abcdef.documents.azure.com:443/abcd'); - }); - - test(`Invalid connection strings`, () => { - assert.throws(() => parseDocDBConnectionString('')); - assert.throws(() => parseDocDBConnectionString('AccountKey=abcdef==')); - assert.throws(() => parseDocDBConnectionString('AccountEndpoint=https://abcdef.documents.azure.com:443/')); - assert.throws(() => parseDocDBConnectionString('mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb')); - }); -}); diff --git a/test/documentLabel.test.ts b/test/documentLabel.test.ts deleted file mode 100644 index 29cde94c8..000000000 --- a/test/documentLabel.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { getDocumentTreeItemLabel } from '../extension.bundle'; - -suite("Document Label Tests", () => { - test("Non-zero number", () => { - const doc = { name: 4, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), 4); - }); - - test("zero (number)", () => { - const doc = { name: 0, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), 0); - }); - - test("Empty string", () => { - const doc = { name: "", _id: "" }; - assert.equal(getDocumentTreeItemLabel(doc), ""); - }); - - test("Null", () => { - const doc = { name: null, _id: "12345678901234567890123456789012" }; - assert.equal(getDocumentTreeItemLabel(doc), doc._id); - }); -}); diff --git a/test/global.test.ts b/test/global.test.ts deleted file mode 100644 index f3fd38670..000000000 --- a/test/global.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TestOutputChannel, TestUserInput } from '@microsoft/vscode-azext-dev'; -import * as vscode from 'vscode'; -import { ext, registerOnActionStartHandler } from '../extension.bundle'; - -// Runs before all tests -suiteSetup(async function (this: Mocha.Context): Promise { - this.timeout(2 * 60 * 1000); - await vscode.commands.executeCommand('azureDatabases.refresh'); // activate the extension before tests begin - ext.outputChannel = new TestOutputChannel(); - - registerOnActionStartHandler(context => { - // Use `TestUserInput` by default so we get an error if an unexpected call to `context.ui` occurs, rather than timing out - context.ui = new TestUserInput(vscode); - }); -}); diff --git a/test/improveError.test.ts b/test/improveError.test.ts deleted file mode 100644 index 25ae0a35e..000000000 --- a/test/improveError.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { improveError } from '../extension.bundle'; - -suite("improveError", () => { - test("no change", () => { - const msg: string = "where is c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe?"; - const improved: unknown = improveError(msg); - - assert.equal(parseError(improved).message, msg); - }); - - test("spawn ENOENT", () => { - const msg: string = "spawn c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe ENOENT"; - const improved: unknown = improveError(msg); - - assert.equal(parseError(improved).message, "Could not find c:\\Program Files\\MongoDB\Server\\4.0\\bin\\mongo.exe"); - }); -}); diff --git a/test/index.ts b/test/index.ts deleted file mode 100644 index bfb035776..000000000 --- a/test/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as glob from 'glob'; -import * as Mocha from 'mocha'; -import * as path from 'path'; - -export async function run(): Promise { - const options: Mocha.MochaOptions = { - ui: 'tdd', - color: true, - reporter: 'mocha-multi-reporters', - reporterOptions: { - reporterEnabled: 'spec, mocha-junit-reporter', - mochaJunitReporterReporterOptions: { - mochaFile: path.resolve(__dirname, '..', '..', 'test-results.xml') - } - } - }; - - addEnvVarsToMochaOptions(options); - console.log(`Mocha options: ${JSON.stringify(options, undefined, 2)}`); - - const mocha = new Mocha(options); - console.log("get files"); - const files: string[] = await new Promise((resolve, reject) => { - // tests in unit/ folder must run without vscode context. - // Skip them when running integration tests in a vscode instance. - glob('{!(unit)/,}*.test.js', { cwd: __dirname }, (err, result) => { - err ? reject(err) : resolve(result); - }); - }); - files.forEach(f => mocha.addFile(path.resolve(__dirname, f))); - - const failures = await new Promise(resolve => mocha.run(resolve)); - if (failures > 0) { - throw new Error(`${failures} tests failed.`); - } -} - -function addEnvVarsToMochaOptions(options: Mocha.MochaOptions): void { - for (const envVar of Object.keys(process.env)) { - const match: RegExpMatchArray | null = envVar.match(/^mocha_(.+)/i); - if (match) { - const [, option] = match; - let value: string | number = process.env[envVar] || ''; - if (typeof value === 'string' && !isNaN(parseInt(value))) { - value = parseInt(value); - } - (options)[option] = value; - } - } -} diff --git a/test/mongoConnectionStrings.test.ts b/test/mongoConnectionStrings.test.ts deleted file mode 100644 index 4560342a7..000000000 --- a/test/mongoConnectionStrings.test.ts +++ /dev/null @@ -1,165 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { addDatabaseToAccountConnectionString, emulatorPassword, encodeMongoConnectionString, getDatabaseNameFromConnectionString, isCosmosEmulatorConnectionString } from '../extension.bundle'; - -function testDatabaseToAccountConnectionString(connectionString: string, databaseName: string, expectedConnectionString: string | undefined): void { - const databaseConnectionString = addDatabaseToAccountConnectionString(connectionString, databaseName); - assert.equal(databaseConnectionString, expectedConnectionString); -} - -function testDatabaseNameFromConectionString(connectionString: string, expectedDatabaseName: string | undefined): void { - const databaseName = getDatabaseNameFromConnectionString(connectionString); - assert.equal(databaseName, expectedDatabaseName); -} - -function testIsCosmosEmulatorConnectionString(connectionString: string, expected: boolean): void { - const actual: boolean = isCosmosEmulatorConnectionString(connectionString); - assert.equal(actual, expected); -} - -function testEncodeMongoConnectionString(connectionString: string, expectedConnectionString: string): void { - connectionString = encodeMongoConnectionString(connectionString); - assert.equal(connectionString, expectedConnectionString); -} - -suite(`mongoCollectionStrings`, () => { - test(`getDatabaseNameFromConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - testDatabaseNameFromConectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, undefined); - testDatabaseNameFromConectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, 'our-mongo'); - - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, undefined); - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, undefined); - testDatabaseNameFromConectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/dbname`, `dbname`); - - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, undefined); - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test`, 'my-database'); - - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, undefined); - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, undefined); - testDatabaseNameFromConectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/db`, 'db'); - - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/`, undefined); - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/db`, 'db'); - - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, undefined); - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB`, 'MYDB'); - - testDatabaseNameFromConectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, undefined); - testDatabaseNameFromConectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, 'my_db'); - testDatabaseNameFromConectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, undefined); - testDatabaseNameFromConectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, 'hello'); - testDatabaseNameFromConectionString(`mongodb://localhost`, undefined); - testDatabaseNameFromConectionString(`mongodb://localhost/db`, 'db'); - testDatabaseNameFromConectionString(`mongodb://sysop:moon@localhost/records`, 'records'); - testDatabaseNameFromConectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/db`, 'db'); - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc`, 'abc'); - - // special characters - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl`, 'def-ghi_jkl'); - testDatabaseNameFromConectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/Icantlikespaces`, 'Icantlikespaces'); - - // emulator: mongodb://localhost:C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==@localhost:10255?ssl=true - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin?ssl=true`, 'admin'); - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin-master?ssl=true`, 'admin-master'); - // test characters mentioned in : https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Database-Names-for-Windows - testDatabaseNameFromConectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin!@%^()-_,[]?ssl=true`, 'admin!@%^()-_,[]'); - - }); - - test('addDatabaseToAccountConnectionString', () => { - testDatabaseToAccountConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, 'somedatabase', 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/somedatabase?ssl=true&replicaSet=globaldb'); - testDatabaseToAccountConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, 'our-mongo', 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb'); - - testDatabaseToAccountConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, 'mydata', 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/mydata'); - testDatabaseToAccountConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, 'database', 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/database'); - testDatabaseToAccountConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, 'database', 'mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database'); - - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, 'my-database', 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test'); - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, 'my-database', 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?'); - - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, 'undefined', 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined'); - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, 'undefined', 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined'); - testDatabaseToAccountConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, '(NoSQL)data', 'mongodb://r1.example.net:27017,r2.example.net:27017/(NoSQL)data'); - - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, 'undefined', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/undefined?replicaSet=mySet&authSource=authDB'); - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, 'MYDB', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB'); - - testDatabaseToAccountConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, 'basetoadd', 'mongodb+srv://server.example.com/basetoadd?connectTimeoutMS=300000&authSource=aDifferentAuthDB?'); - - testDatabaseToAccountConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, '', 'mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB'); - testDatabaseToAccountConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, 'not_mydatabase', 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/not_mydatabase?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB'); - testDatabaseToAccountConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, '', 'mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000'); - testDatabaseToAccountConnectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, 'hellno', 'mongodb://host.example.com/hellno?readPreference=secondary&maxStalenessSeconds=120'); - testDatabaseToAccountConnectionString(`mongodb://localhost`, '', 'mongodb://localhost/'); - testDatabaseToAccountConnectionString(`mongodb://localhost/db`, 'new{}db', `mongodb://localhost/${encodeURIComponent("new{}db")}`); - testDatabaseToAccountConnectionString(`mongodb://sysop:moon@localhost/records`, 'records', 'mongodb://sysop:moon@localhost/records'); - testDatabaseToAccountConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, 'notfun', 'mongodb://%2Ftmp%2Fmongodb-27017.sock/notfun'); - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, 'notsure', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/notsure?ssl=true'); - - // special characters - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, 'def-ghi_jkl', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl?'); - testDatabaseToAccountConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, 'icantlikespaces', 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/icantlikespaces'); - - // Emulator - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin?ssl=true`); - // Collection within emulator - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin-master', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/admin-master?ssl=true`); - testDatabaseToAccountConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, 'admin!@%^()-_,[]', `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/${encodeURIComponent("admin!@%^()-_,[]")}?ssl=true`); - }); - - test('isCosmosEmulatorConnectionString', () => { - testIsCosmosEmulatorConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, false); - testIsCosmosEmulatorConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, false); - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, false); - testIsCosmosEmulatorConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, false); - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, false); - - testIsCosmosEmulatorConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, false); - testIsCosmosEmulatorConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, false); - testIsCosmosEmulatorConnectionString(`mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost/db`, false); - testIsCosmosEmulatorConnectionString(`mongodb://sysop:moon@localhost/records`, false); - testIsCosmosEmulatorConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, false); - - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc...`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, false); - testIsCosmosEmulatorConnectionString(`mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, false); - - // Emulator - testIsCosmosEmulatorConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, true); - testIsCosmosEmulatorConnectionString(`mongodb://127.0.0.1:${encodeURIComponent(emulatorPassword)}@127.0.0.1:10255/?ssl=true`, true); - testIsCosmosEmulatorConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/database?ssl=true`, true); - }); - - test('encodeMongoConnectionString', () => { - testEncodeMongoConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg%3D%3D@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`); - testEncodeMongoConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`); - testEncodeMongoConnectionString(`mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`); - testEncodeMongoConnectionString(`mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`); - testEncodeMongoConnectionString(`mongodb://localhost`, `mongodb://localhost`); - testEncodeMongoConnectionString(`mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:10255/?ssl=true`, `mongodb://localhost:${encodeURIComponent(encodeURIComponent(emulatorPassword))}@localhost:10255/?ssl=true`); - testEncodeMongoConnectionString(`mongodb://username@example.com:password@localhost/`, `mongodb://username%40example.com:password@localhost/`); - testEncodeMongoConnectionString(`mongodb://crazy@:/%username:even@crazier%/password@localhost/`, `mongodb://crazy%40%3A%2F%25username:even%40crazier%25%2Fpassword@localhost/`); - }); -}); diff --git a/test/mongoGetCommand.test.ts b/test/mongoGetCommand.test.ts deleted file mode 100644 index 5a72eae5e..000000000 --- a/test/mongoGetCommand.test.ts +++ /dev/null @@ -1,1138 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { Position } from 'vscode'; -import { findCommandAtPosition, getAllCommandsFromText, MongoCommand, nonNullProp, ObjectID, ObjectId } from '../extension.bundle'; - -function expectSingleCommand(text: string): MongoCommand { - const commands = getAllCommandsFromText(text); - if (commands.length > 1) { - assert.ok(false, "Too many commands found"); - } - - return commands[0]; -} - -function testParse( - text: string, - expectedCommand: { collection: string | undefined, name: string | undefined, args: any[] | undefined, firstErrorText?: string } | undefined -): void { - function testCore(coreText: string): void { - const command = expectSingleCommand(coreText); - if (expectedCommand) { - assert.ok(command, "Expected a command, but found none"); - - assert.equal(command.collection || "", expectedCommand.collection || "", "Parsed collection name is not correct"); - assert.equal(command.name || "", expectedCommand.name || "", "Parsed command name is not correct"); - - const actualArgs = (command.arguments || []).map(arg => JSON.parse(arg)); - assert.deepEqual(actualArgs, expectedCommand.args || [], "Parsed arguments are not correct"); - - } else { - assert.ok(!command, "Found a command, but expecting to find none"); - return; - } - - if (expectedCommand && expectedCommand.firstErrorText) { - assert.equal((command.errors || []).length > 0, true, "Expected at least one error"); - assert.equal(nonNullProp(command, 'errors')[0].message, expectedCommand.firstErrorText, "First error text was incorrect"); - } else { - assert.equal((command.errors || []).length, 0, "Expected no errors"); - } - } - - testCore(text); - - // Test again with LF changed to CR/LF - const crlfText = text.replace(/\n/g, '\r\n'); - testCore(crlfText); - - // Test again with LF changed to multiple CR/LF - const crlf2Text = text.replace(/\n/g, '\r\n\r\n'); - testCore(crlf2Text); - - // Test again with LF changed to CR - const lfText = text.replace(/\n/g, '\r'); - testCore(lfText); - - // Test again with LF changed to tab - const tabText = text.replace(/\n/g, '\t'); - testCore(tabText); - - // Test again with LF changed to space - const spaceText = text.replace(/\n/g, ' '); - testCore(spaceText); -} - -function wrapInQuotes(word: string, numQuotes: number): string { //0 to do nothing, 1 for single quotes, 2 for double quotes - let result: string; - if (numQuotes === 1) { - result = `'${word}'`; - } else if (numQuotes === 2) { - result = `"${word}"`; - } else { - result = word; - } - return result; -} - -suite("scrapbook parsing Tests", () => { - test("find", () => { - const text = "db.find()"; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test("find with semicolon", () => { - const text = "db.find();"; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test("first of two commands, Mac/Linux", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test("second of two commands, Mac/Linux", () => { - const line1 = "db.find()"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test("second of two commands, Mac/Linux, semicolon", () => { - const line1 = "db.find();"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test("first of two commands, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test("second of two commands, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a':'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - }); - - test("second of two commands, lots of blank lines, Windows", () => { - const line1 = "db.find()"; - const line2 = "db.insertOne({'a':'b'})"; - const text = `\r\n\r\n\r\n\r\n\r\n\r\n${line1}\r\n\r\n\r\n\r\n\r\n\r\n${line2}\r\n\r\n\r\n\r\n\r\n\r\n`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(5, 0)); - assert.equal(command.text, line2); - }); - - test("first of two commands, Windows, on blank line before second command", () => { - const line1 = "db.find()"; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes("a", q)}:1})`; - const text = `${line1}\r\n\r\n\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line1); - } - }); - - test("drop", () => { - testParse( - `db.test.drop()`, - { collection: "test", name: "drop", args: [] }); - }); - - test("find, with empty object argument", () => { - testParse( - `db.test.find({})`, - { collection: "test", name: "find", args: [{}] }); - }); - - test("end-of-line comment", () => { - testParse( - `db.test.drop() // Ignore error "ns not found", it means "test" does not exist yet`, - { collection: "test", name: "drop", args: [] }); - }); - - test("multi-line insert from #214", () => { - for (let q = 0; q <= 2; q++) { - testParse( - `db.heroes.insert({\n${wrapInQuotes("id", q)}: 2,\r\n${wrapInQuotes("name", q)}: "Batman",\r\n\r\n${wrapInQuotes("saying", q)}: "I'm Batman"\r})`, - { - collection: "heroes", name: "insert", args: [ - { - id: 2, - name: "Batman", - saying: "I'm Batman" - } - ] - }); - } - }); - - test("find/project from #214", () => { - testParse( - `db.heroes.find({ "id": 2 }, { "saying": 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - }, - { - saying: 1 - } - ] - }); - }); - - test("extraneous input", () => { - testParse( - `db.heros.find(); - hello there`, - { - collection: "heros", - name: "find", - args: [], - firstErrorText: "mismatched input 'hello' expecting " - } - ); - }); - - test("empty", () => { - testParse( - "// hello there", - undefined - ); - }); - - test("no command found, errors (will be tacked on to a blank command)", () => { - testParse( - "hello there", - { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input 'hello' expecting " - } - ); - }); - - test("expect error: missing comma in arguments", () => { - testParse( - `db.heroes.find({ "id": 2 } { "saying": 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - } - ], - firstErrorText: "mismatched input '{' expecting {',', ')'}" - } - ); - - testParse( - `db.c.find({"a":[1,2,3]"b":1});`, - { - collection: 'c', - name: 'find', - args: [{ a: [1, 2, 3] }], - firstErrorText: "mismatched input '\"b\"' expecting {',', '}'}" - } - ); - - }); - - //https://github.com/Microsoft/vscode-cosmosdb/issues/467 - test("single quoted property names", () => { - testParse( - `db.heroes.find({ 'id': 2 }, { 'saying': 1 })`, - { - collection: "heroes", name: "find", args: [ - { - id: 2 - }, - { - saying: 1 - } - ] - }); - }); - test("expect error: missing function name", () => { - // From https://github.com/Microsoft/vscode-cosmosdb/issues/659 - testParse( - `db.c1.`, - { - collection: "c1", - name: "", - args: [], - firstErrorText: "mismatched input '' expecting IDENTIFIER" - } - ); - - testParse( - `db.c1.;`, - { - collection: "c1", - name: "", - args: [], - firstErrorText: "mismatched input ';' expecting IDENTIFIER" - } - ); - - testParse( - `db.c1.(1, "a");`, - { - collection: "c1", - name: "", - args: [ - 1, - 'a' - ], - firstErrorText: "missing IDENTIFIER at '('" - } - ); - - testParse( - `..(1, "a");`, - { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input '.' expecting " - } - ); - - // Just make sure doesn't throw - expectSingleCommand(`db..(1, "a");`); - expectSingleCommand(`..c1(1, "a");`); - }); - - test("multi-line insert from #214", () => { - testParse( - `db.heroes.insert({\n"id": 2,\r\n"name": "Batman",\r\n\r\n"saying": "I'm Batman"\r})`, - { - collection: "heroes", name: "insert", args: [ - { - id: 2, - name: "Batman", - saying: "I'm Batman" - } - ] - }); - }); - - test("Array followed by } on separate line, from #73", () => { - testParse( - `db.createUser({ - "user": "buddhi", - "pwd": "123", - "roles": ["readWrite", "dbAdmin"] - } - )`, - { - collection: undefined, - name: "createUser", - args: [ - { - user: "buddhi", - pwd: "123", - roles: ["readWrite", "dbAdmin"] - } - ] - }); - }); - - test("Multiple line arrays, from #489", () => { - testParse( - ` - db.c2.insertMany([ - {"name": "Stephen", "age": 38, "male": true}, - {"name": "Stephen", "age": 38, "male": true} - ]) - `, - { - collection: "c2", - name: "insertMany", - args: [ - [ - { - name: "Stephen", - age: 38, - male: true - }, - { - name: "Stephen", - age: 38, - male: true - } - ] - ] - }); - }); - - test("test function call that has 2 arguments", () => { - const arg0 = `{"Age": 31}`; - const arg1 = `{"Name": true}`; - const text = `db.find(${arg0}\r\n,\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test("test function call with nested parameters - documents in an array", () => { - const arg0 = `[{"name": "a"}, {"name": "b"}, {"name": "c"}]`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0},\r\n\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test("test function call that has a nested parameter", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const text = `db.test1.insertMany(${arg0})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - }); - test("test function call with erroneous syntax: missing comma", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0} ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 61); - }); - test("test function call with erroneous syntax: missing comma, parameters separated with newline", () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": \ntrue}`; - const text = `db.test1.insertMany(${arg0} \n ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 1); - assert.deepEqual(err.range.start.character, 2); - }); - test("test function call with erroneous syntax: missing double quote", () => { - const text = `db.test1.insertMany({name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "missing \':\' at '\": {\"'"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 25); - }); - test("test function call with erroneous syntax: missing opening brace", () => { - const text = `db.test1.insertMany("name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input ':' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 26); - }); - - test("Chained command: to use pretty()", () => { - testParse('db.timesheets.find().pretty();', { - collection: "timesheets", - name: "pretty", - args: [] - }); - }); - - test("ISODate with standard date string", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00Z") });', { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: "2018-05-01T00:00:00.000Z" - }, - name: "Stephen" - } - ] - }); - }); - - test("ISODate without Z in date string", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00") });', { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: "2018-05-01T00:00:00.000Z" - }, - name: "Stephen" - } - ] - }); - }); - - test("Invalid ISODate", () => { - testParse('db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00z") });', { - collection: "c1", - name: "insertOne", - args: [], - firstErrorText: "Invalid time value" - }); - }); - - test("Date", () => { - const date: Date = new Date("2018-05-01T00:00:00"); - testParse(`db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": Date("${date.toUTCString()}") });`, { - collection: "c1", - name: "insertOne", - args: [ - { - _id: { - $oid: "5aecf1a63d8af732f07e4275" - }, - date: { - $date: date.toString() - }, - name: "Stephen" - } - ] - }); - }); - - test("Keys with periods", () => { - testParse( - `db.timesheets.update( { - "year":"2018", - "month":"06" - },{ - "$set":{ - "workers.0.days.0.something":"yupy!" - } - }); - `, - { - collection: "timesheets", - name: "update", - args: [ - { - year: 2018, - month: "06" - }, - { - $set: { - "workers.0.days.0.something": "yupy!" - } - } - ] - }); - }); - - test("nested objects", () => { - testParse( - `db.users.update({},{ - "$pull":{ - "proposals":{ - "$elemMatch":{"_id":"4qsBHLDCb755c3vPH"} - } - } - })`, - { - collection: "users", - name: "update", - args: [ - {}, - { - $pull: { - proposals: { - $elemMatch: { - _id: "4qsBHLDCb755c3vPH" - } - } - } - } - ] - }); - }); - test("test function call with and without quotes", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.test1.insertMany({${wrapInQuotes("name", q)}: 'First' })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "First" }]); - } - }); - test("test function call with numbers", () => { - const text = `db.test1.insertMany({'name': 1010101})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: 1010101 }]); - }); - test("test function call boolean", () => { - const text = `db.test1.insertMany({'name': false})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: false }]); - }); - test("test function call token inside quotes", () => { - const text = `db.test1.insertMany({'name': 'false'})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "false" }]); - }); - test("test function call with an empty string property value", () => { - const text = `db.test1.insertMany({'name': ''})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: "" }]); - }); - test("test function call with array and multiple arguments", () => { - const text = `db.test1.find({'roles': ['readWrite', 'dbAdmin']}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ roles: ["readWrite", "dbAdmin"] }, { resources: ["secondary", "primary"] }]); - }); - test("test function call with nested objects", () => { - const text = `db.test1.find({'roles': [{'optional': 'yes'}]}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ roles: [{ optional: "yes" }] }, { resources: ["secondary", "primary"] }]); - }); - - test("test incomplete function call - replicate user typing - no function call yet", () => { - const text = `db.test1.`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, []); - assert.deepEqual(command.collection, "test1"); - }); - - test("test incomplete function call - replicate user typing - missing propertyValue", () => { - const text = `db.test1.find({"name": {"First" : } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test("test incomplete function call - replicate user typing - missing colon & propertyValue", () => { - const text = `db.test1.find({"name": {"First" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test("test incomplete function call - replicate user typing - empty array as argument", () => { - const text = `db.heroes.aggregate([\n])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [[]]); - }); - - test("test quotes inside a string - 1", () => { - const text = `db.test1.find("That's all")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That's all"]); - }); - - test("test quotes inside a string - 2", () => { - const text = `db.test1.find('That"s all')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That\"s all"]); - }); - - // Note: when escaping a character, escape it twice. - test("test quotes inside a string - 3", () => { - const text = `db.test1.find("Hello \\"there\\"")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ['Hello \\"there\\"']); - }); - - test("test quotes inside a string - 4", () => { - const text = `db.test1.find('Hello \\'there\\'')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["Hello \\'there\\'"]); - }); - - test("test nested property names (has dots in the name)", () => { - const text = `db.test1.find({"name.FirstName": 1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ "name.FirstName": 1 }]); - }); - - test("test managed namespace collection names (has dots in the name)", () => { - const text = `db.test1.beep.find({})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "test1.beep"); - }); - - test("test aggregate query", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.orders.aggregate([ - { ${wrapInQuotes("$match", q)}: { ${wrapInQuotes("status", q)} : "A" } }, - { ${wrapInQuotes("$group", q)}: { ${wrapInQuotes("_id", q)}: "$cust_id", ${wrapInQuotes("total", q)}: { ${wrapInQuotes("$sum", q)}: "$amount" } } }, - { ${wrapInQuotes("$sort", q)}: { ${wrapInQuotes("total", q)}: -1 } } - ], - { - ${wrapInQuotes("cursor", q)}: { ${wrapInQuotes("batchSize", q)}: 0 } - })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "orders"); - assert.deepEqual(command.argumentObjects, [[ - { $match: { status: "A" } }, - { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, - { $sort: { total: -1 } } - ], - { - cursor: { batchSize: 0 } - }]); - } - }); - - test("test ObjectID - no parameter", () => { - const text = `db.c1.insert({"name": ObjectId()})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - assert.ok((nonNullProp(command, 'argumentObjects')[0]).name instanceof ObjectID); - }); - - test("test ObjectID - hex", () => { - const idParam = "abcdef123456789012345678"; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - const id = new ObjectID(idParam); - assert.deepEqual(command.argumentObjects, [{ name: id }]); - }); - - test("test faulty ObjectID - hex - extra characters", () => { - const idParam = "abcdef12345678901234567890"; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const errorMessage = "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, errorMessage); - }); - - test("test faulty ObjectID - hex - fewer characters", () => { - const idParam = "abcdef123456789012345"; - for (let i = 1; i < 3; i++) { - const text = `db.c1.insert({"name": ObjectId(${wrapInQuotes(idParam, i)})})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const errorMessage = "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"; - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, errorMessage); - } - }); - //Examples inspired from https://docs.mongodb.com/manual/reference/operator/query/regex/ - test("test regular expressions - only pattern, no flags", () => { - const text = `db.test1.beep.find({ sku: /789$/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, ""); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - pattern and flags", () => { - const text = `db.test1.beep.find({ sku: /789$/i } )`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "i"); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - Intellisense - flag contains invalid option", () => { - const text = `db.test1.beep.find({ sku: /789$/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - const err = parseError(error); - assert.deepEqual("Unexpected node encountered", err.message); - } - }); - - test("test regular expressions - wrong escape - throw error", () => { - const text = `db.test1.beep.find({ sku: /789$\\/b\\/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - assert.equal(error.message, "Invalid regular expression: /789$\\/b\\/: \\ at end of pattern"); - } - }); - - //Passing the following test should imply the rest of the tests pass too. - // The regex parsing tests following this test should help zero-in on which case isn't handled properly. - test("test regular expression parsing - with many special cases", () => { - const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"); - }); - - test("test regular expression parsing EJSON syntax - with many special cases", () => { - const text = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"); - }); - - test("test regular expression parsing interoperability", () => { - const text1 = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/g })`; - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$"]); - }); - - test("test regular expression parsing interoperability - word break", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\b/g })`; // equivalent to user typing out /ker\b/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\b", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\b"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\b"]); - }); - - test("test regular expression parsing interoperability - newline", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\n/g })`; // equivalent to user typing out /ker\n/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\n", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\n"]); - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\n"]); - }); - test("test regular expression parsing interoperability - carriage return", () => { - const text1 = `db.test1.beep.find({ sku: /ker\\r/g })`; // equivalent to user typing out /ker\r/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\r", $options: "g"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.flags, generatedRegExp1.source], ["g", "ker\\r"]); - assert.deepEqual([generatedRegExp2.flags, generatedRegExp2.source], ["g", "ker\\r"]); - }); - - test("test regular expressions - only pattern, no flags", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, ""); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - pattern and flags", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"i" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "i"); - assert.deepEqual(generatedRegExp.source, "789$"); - }); - - test("test regular expressions - Intellisense - flag contains invalid option", () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"q" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, "Invalid flags supplied to RegExp constructor 'q'"); - assert.deepEqual(nonNullProp(command, 'errors')[0].range.start.character, 19); - }); - - test("test regular expression parsing - with groupings", () => { - const text = `db.test1.beep.find({ sku: /(?:hello)\\3/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(?:hello)\\3"); - }); - - test("test regular expression parsing - with special characters", () => { - const text = `db.test1.beep.find({ sku: /(hello)*(world)?(name)+./g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello)*(world)?(name)+."); - }); - - test("test regular expression parsing - with boundaries", () => { - const text = `db.test1.beep.find({ sku: /^(hello world)[^0-9]|(world\\b)$/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "^(hello world)[^0-9]|(world\\b)$"); - }); - - test("test regular expression parsing - with quantifiers", () => { - const text = `db.test1.beep.find({ sku: /(hello)*[^0-9]+|(world){0,2}./g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello)*[^0-9]+|(world){0,2}."); - }); - - test("test regular expression parsing - with conditional", () => { - const text = `db.test1.beep.find({ sku: /(hello?= world)|(world)/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "(hello?= world)|(world)"); - }); - - test("test regular expression parsing - with escaped special characters", () => { - const text = `db.test1.beep.find({ sku: /world\\*\\.\\?\\+/g })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.flags, "g"); - assert.deepEqual(generatedRegExp.source, "world\\*\\.\\?\\+"); - }); - - test("test chained command: argument aggregation", () => { - testParse('db.timesheets.find({name: "Andy", surname: "Jackson"}).pretty();', { - collection: "timesheets", - name: "pretty", - args: [{ name: "Andy", surname: "Jackson" }] - }); - }); - - test("Chained command - order of parsed arguments", () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1}).skip(40);', { - collection: "timesheets", - name: "skip", - args: [{ name: "Andy" }, { age: 1 }, 40] - }); - }); - - test("Chained command - missing period", () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1})skip(40);', { - collection: "timesheets", - name: "sort", - args: [{ name: "Andy" }, { age: 1 }], - firstErrorText: "mismatched input 'skip' expecting " - }); - }); - - test("Chained command - mid-type - missing bracket", () => { - testParse('db.timesheets.find({name:"Andy"}).sort', { - collection: "timesheets", - name: "sort", - args: [{ name: "Andy" }], - firstErrorText: "mismatched input '' expecting '('" - }); - }); - - test("Chained command - mid-type - typed the dot, but not the function call", () => { - testParse('db.timesheets.find({name:"Andy"}).', { - collection: "timesheets", - name: "", - args: [{ name: "Andy" }], - firstErrorText: "mismatched input '' expecting IDENTIFIER" - }); - }); - - //TODO: Tests to simulate cases where the user hasn't completed typing - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/688", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.hdr.aggregate([ - { ${wrapInQuotes("$match", q)}: { "CURRENCY_ID": "USD" } }, - ])`; //Note the trailing comma. There should be 1 argument object returned, an array, that has 2 elements - //one expected, and another empty object. - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "hdr"); - assert.deepEqual(command.argumentObjects, [[{ $match: { CURRENCY_ID: "USD" } }, {}]]); - } - }); - - test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/785", () => { - testParse('db.timesheets.find({name:"Andy"}).count();', { - collection: "timesheets", - name: "count", - args: [{ name: "Andy" }] - }); - }); - - test("Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/795", () => { - testParse('db.timesheets.find({}).limit(10);', { - collection: "timesheets", - name: "limit", - args: [{}, 10] - }); - }); - - test("Chained command alternative for rs.slaveOk()- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/565", () => { - testParse('db.getMongo().setSlaveOk();', { - collection: "", - name: "setSlaveOk", - args: [] - }); - }); - - test("Multiple line command, from #489", () => { - testParse( - ` - db.finalists.find({name: "Jefferson"}) - . - limit - (10); - `, - { - collection: "finalists", - name: "limit", - args: [ - { - name: "Jefferson" - }, - 10 - ] - }); - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/703", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({ ${wrapInQuotes("user", q)}: { ${wrapInQuotes("$in", q)}: [ "A80", "HPA" ] } },{ ${wrapInQuotes("_id", q)}: false });`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "Users"); - assert.deepEqual(command.argumentObjects, [{ user: { $in: ["A80", "HPA"] } }, { _id: false }]); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/691", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.users.aggregate([ - { ${wrapInQuotes("$match", q)}: {${wrapInQuotes("_id", q)}: {"$oid" :"5b23d2ba92b52cf794bdeb9c")}}}, - { ${wrapInQuotes("$project", q)}: { - ${wrapInQuotes("scores", q)}: {${wrapInQuotes("$filter", q)}: { - ${wrapInQuotes("input", q)}: '$scores', - ${wrapInQuotes("as", q)}: 'score', - ${wrapInQuotes("cond", q)}: {${wrapInQuotes("$gt", q)}: ['$$score', 3]} - }} - }} - ])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "users"); - assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][0], { $match: { _id: new ObjectId("5b23d2ba92b52cf794bdeb9c") } }); - assert.deepEqual( - nonNullProp(command, 'argumentObjects')[0][1], - { - $project: { - scores: { - $filter: { - input: '$scores', - as: 'score', - cond: { $gt: ['$$score', 3] } - } - } - } - }); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/717", () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({${wrapInQuotes("age", q)} : { ${wrapInQuotes("$in", q)} : [19, 20, 22, 25]}});`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "Users"); - assert.deepEqual(command.argumentObjects, [{ age: { $in: [19, 20, 22, 25] } }]); - } - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/737", () => { - const text = `db.c1.insert({},f)`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, "c1"); - assert.deepEqual(command.argumentObjects, [{}, {}]); - assert.deepEqual(nonNullProp(command, 'errors')[0].message, "mismatched input 'f' expecting {'{', '[', RegexLiteral, StringLiteral, 'null', BooleanLiteral, NumericLiteral}"); - }); - - test("test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/899 - multi-line comment, not regex", () => { - for (const escape of ['\n', '\r', '\n\r', '\r\n']) { - const text = `db.heroes.count()${escape}/*db.c2.insertMany([${escape}{"name": "Stephen", "age": 38, "male": true},${escape}{"name": "Stephen", "age": 38, "male": true}${escape}]);${escape}*/${escape}${escape}db.heroes.find();`; - const commands = getAllCommandsFromText(text); - assert.equal(commands.length, 2, `Error in parsing ${text}`); - assert.equal(commands[0].name, "count"); - assert.equal(commands[1].name, "find"); - } - }); -}); diff --git a/test/mongoShell.test.ts b/test/mongoShell.test.ts deleted file mode 100644 index 83fdb845e..000000000 --- a/test/mongoShell.test.ts +++ /dev/null @@ -1,288 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// CONSIDER: Run in pipeline -import * as assert from 'assert'; -import * as cp from "child_process"; -import * as fse from 'fs-extra'; -import * as os from 'os'; -import * as path from 'path'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { ext, IDisposable, isWindows, MongoShell, parseError } from '../extension.bundle'; -import { runWithSetting } from './runWithSetting'; -import { setEnvironmentVariables } from './util/setEnvironmentVariables'; - -const VERBOSE = false; // If true, the output from the Mongo server and shell will be sent to the console for debugging purposes - -let testsSupported: boolean = true; - -if (!isWindows) { - // CONSIDER: Non-Windows - console.warn(`Not running in Windows - skipping MongoShell tests`); - testsSupported = false; -} - -suite("MongoShell", async function (this: Mocha.Suite): Promise { - // https://github.com/mochajs/mocha/issues/2025 - this.timeout(10000); - - async function testIfSupported(title: string, fn?: Mocha.Func | Mocha.AsyncFunc): Promise { - await runWithSetting(ext.settingsKeys.mongoShellTimeout, '60', async () => { - if (testsSupported) { - test(title, fn); - } else { - test(title); - } - }); - } - - // CONSIDER: Make more generic - let mongodCP: cp.ChildProcess; - const mongodPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongod.exe"; - const mongoPath = "c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongo.exe"; - let mongoDOutput = ""; - let mongoDErrors = ""; - let isClosed = false; - - if (!fse.existsSync(mongodPath)) { - console.log(`Couldn't find mongod.exe at ${mongodPath} - skipping MongoShell tests`); - testsSupported = false; - } else if (!fse.existsSync(mongodPath)) { - console.log(`Couldn't find mongo.exe at ${mongoPath} - skipping MongoShell tests`); - testsSupported = false; - } else { - // Prevent code 100 error: https://stackoverflow.com/questions/41420466/mongodb-shuts-down-with-code-100 - await fse.ensureDir('D:\\data\\db\\'); - } - - class FakeOutputChannel implements vscode.OutputChannel { - public name: string; - public output: string; - - public append(value: string): void { - assert(value !== undefined); - assert(!value.includes('undefined')); - this.output = this.output ? this.output + os.EOL + value : value; - log(value, "Output channel: "); - } - public appendLine(value: string): void { - assert(value !== undefined); - this.append(value + os.EOL); - } - public clear(): void { } - public show(preserveFocus?: boolean): void; - public show(column?: vscode.ViewColumn, preserveFocus?: boolean): void; - public show(_column?: any, _preserveFocus?: any): void { } - public hide(): void { } - public dispose(): void { } - public replace(_value: string): void { } - } - - function log(text: string, linePrefix: string): void { - text = text.replace(/(^|[\r\n]+)/g, "$1" + linePrefix); - if (VERBOSE) { - console.log(text); - } - } - - async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); - } - - function executeInShell(command: string): string { - return cp.execSync(command, {}).toString(); - } - - suiteSetup(() => { - if (testsSupported) { - assert(fse.existsSync(mongodPath), "Couldn't find mongod.exe at " + mongodPath); - assert(fse.existsSync(mongoPath), "Couldn't find mongo.exe at " + mongoPath); - - // Shut down any still-running mongo server - try { - executeInShell('taskkill /f /im mongod.exe'); - } catch (error) { - assert(/The process .* not found/.test(parseError(error).message), `Error killing mongod: ${parseError(error).message}`); - } - - mongodCP = cp.spawn(mongodPath, ['--quiet']); - - mongodCP.stdout?.on("data", (buffer: Buffer) => { - log(buffer.toString(), "mongo server: "); - mongoDOutput += buffer.toString(); - }); - mongodCP.stderr?.on("data", (buffer: Buffer) => { - log(buffer.toString(), "mongo server STDERR: "); - mongoDErrors += buffer.toString(); - }); - mongodCP.on("error", (error: unknown) => { - log(parseError(error).message, "mongo server Error: "); - mongoDErrors += parseError(error).message + os.EOL; - }); - mongodCP.on("close", (code?: number) => { - console.log(`mongo server: Close code=${code}`); - isClosed = true; - if (isNumber(code) && code !== 0) { - mongoDErrors += `mongo server: Closed with code "${code}"${os.EOL}`; - } - }); - } - }); - - suiteTeardown(() => { - if (mongodCP) { - mongodCP.kill(); - } - }); - - await testIfSupported("Verify mongod running", async () => { - while (!mongoDOutput.includes('waiting for connections on port 27017')) { - assert.equal(mongoDErrors, "", "Expected no errors"); - assert(!isClosed); - await delay(50); - } - }); - - async function testShellCommand(options: { - script: string; - expectedResult?: string; - expectedError?: string | RegExp; - expectedOutput?: RegExp; - title?: string; // Defaults to script - args?: string[]; // Defaults to [] - mongoPath?: string; // Defaults to the correct mongo path - env?: { [key: string]: string }; // Add to environment - timeoutSeconds?: number; - }): Promise { - await testIfSupported(options.title || options.script, async () => { - assert(!isClosed); - assert(mongoDErrors === ""); - - let previousEnv: IDisposable | undefined; - let shell: MongoShell | undefined; - const outputChannel = new FakeOutputChannel(); - - try { - previousEnv = setEnvironmentVariables(options.env || {}); - shell = await MongoShell.create(options.mongoPath || mongoPath, options.args || [], '', false, outputChannel, options.timeoutSeconds || 5); - const result = await shell.executeScript(options.script); - if (options.expectedError) { - assert(false, `Expected error did not occur: '${options.expectedError}'`); - } - if (options.expectedResult !== undefined) { - assert.equal(result, options.expectedResult); - } - } catch (error) { - const message = parseError(error).message; - - if (options.expectedError instanceof RegExp) { - assert(options.expectedError.test(message), `Actual error did not match expected error regex. Actual error: ${message}`); - } else if (typeof options.expectedError === 'string') { - assert.equal(message, options.expectedError); - } else { - assert(false, `Unexpected error during the test: ${message}`); - } - - if (options.expectedOutput instanceof RegExp) { - assert(options.expectedOutput.test(outputChannel.output), `Actual contents written to output channel did not match expected regex. Actual output channel contents: ${outputChannel.output}`); - } - } finally { - if (shell) { - shell.dispose(); - } - if (previousEnv) { - previousEnv.dispose(); - } - } - }); - } - - await testShellCommand({ - script: 'use abc', - expectedResult: 'switched to db abc' - }); - - await testShellCommand({ - title: "Incorrect path", - script: 'use abc', - mongoPath: "/notfound/mongo.exe", - expectedError: /Could not find .*notfound.*mongo.exe/ - }); - - await testShellCommand({ - title: "Find mongo through PATH", - script: 'use abc', - mongoPath: "mongo", - expectedResult: 'switched to db abc', - env: { - PATH: process.env.path! + ";" + path.dirname(mongoPath) - } - }); - - await testShellCommand({ - title: "With valid argument", - script: 'use abc', - args: ["--quiet"], - expectedResult: 'switched to db abc' - }); - - await testShellCommand({ - title: "With invalid argument", - script: '', - args: ["--hey-man-how-are-you"], - expectedError: /Error parsing command line: unrecognised option/ - }); - - await testShellCommand({ - title: "Output window may contain additional information", - script: '', - args: ["-u", "baduser", "-p", "badpassword"], - expectedError: /The output window may contain additional information/ - }); - - await testShellCommand({ - title: "With bad credentials", - script: '', - args: ["-u", "baduser", "-p", "badpassword"], - expectedError: /The process exited with code 1/, - expectedOutput: /Authentication failed/ - }); - - await testShellCommand({ - title: "Process exits immediately", - script: '', - args: ["--version"], - expectedError: /The process exited prematurely/ - }); - - await testShellCommand({ - title: "Javascript", - script: "for (var i = 0; i < 123; ++i) { }; i", - expectedResult: "123" - }); - - await testShellCommand({ - title: "Actual timeout", - script: "for (var i = 0; i < 10000000; ++i) { }; i", - expectedError: /Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting./, - timeoutSeconds: 2 - }); - - await testIfSupported("More results than displayed (type 'it' for more -> (More))", async () => { - const shell = await MongoShell.create(mongoPath, [], '', false, new FakeOutputChannel(), 5); - await shell.executeScript('db.mongoShellTest.drop()'); - await shell.executeScript('for (var i = 0; i < 50; ++i) { db.mongoShellTest.insert({a:i}); }'); - - const result = await shell.executeScript('db.mongoShellTest.find().pretty()'); - - assert(!result.includes('Type "it" for more')); - assert(result.includes('(More)')); - - shell.dispose(); - }); -}); diff --git a/test/postgresConnectionStrings.test.ts b/test/postgresConnectionStrings.test.ts deleted file mode 100644 index 3f2ed8da4..000000000 --- a/test/postgresConnectionStrings.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { addDatabaseToConnectionString } from '../extension.bundle'; - -function testAddDatabaseToConectionString(connectionString: string, databaseName: string, expectedConnectionString: string | undefined): void { - const modifiedConnectionString = addDatabaseToConnectionString(connectionString, databaseName); - assert.equal(modifiedConnectionString, expectedConnectionString); -} - -suite(`postgresConnectionStrings`, () => { - test(`addDatabaseToConnectionString`, () => { - // Connection strings follow the following format (https://www.postgresql.org/docs/12/libpq-connect.html): - // postgres://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/`, 'testdb', 'postgres://user:password@test:5432/testdb'); - testAddDatabaseToConectionString(`postgres://user:password@test:5432/testdb`, 'testdb2', `postgres://user:password@test:5432/testdb2`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432`, 'testdb', 'postgres://user:password@test:5432/testdb'); - testAddDatabaseToConectionString(`postgres://user:password@test:5432/?ssl=true&sslmode=require`, 'testdb', `postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/testdb?ssl=true&sslmode=require`, 'testdb2', `postgres://user:password@test:5432/testdb2?ssl=true&sslmode=require`); - - testAddDatabaseToConectionString(`postgres://user:password@test:5432/`, `test%20`, `postgres://user:password@test:5432/test%2520`); - - }); -}); diff --git a/test/runTest.ts b/test/runTest.ts deleted file mode 100644 index f4fe5eb12..000000000 --- a/test/runTest.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron'; -import * as cp from 'child_process'; -import * as path from 'path'; - -async function main(): Promise { - try { - const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); - const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - - cp.spawnSync( - cli, - [ - ...args, - '--install-extension', 'ms-vscode.azure-account', - '--install-extension', 'ms-azuretools.vscode-azureresourcegroups', - ], - { - encoding: 'utf-8', - stdio: 'inherit' - }); - - const repoRoot: string = path.resolve(__dirname, '..', '..'); - await runTests({ - vscodeExecutablePath, - extensionDevelopmentPath: repoRoot, - launchArgs: [ - path.resolve(repoRoot, 'test', 'test.code-workspace'), - '--disable-workspace-trust' - ], - extensionTestsPath: path.resolve(repoRoot, 'dist', 'test', 'index'), - extensionTestsEnv: { - DEBUGTELEMETRY: 'v' - } - }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -void main(); diff --git a/test/runWithSetting.ts b/test/runWithSetting.ts deleted file mode 100644 index 7c095ace6..000000000 --- a/test/runWithSetting.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext, getGlobalSetting, updateGlobalSetting } from "../extension.bundle"; - -export async function runWithDatabasesSetting(key: string, value: string | boolean | undefined, callback: () => Promise): Promise { - await runWithSettingInternal(key, value, ext.prefix, callback); -} - -export async function runWithSetting(key: string, value: string | boolean | undefined, callback: () => Promise): Promise { - await runWithSettingInternal(key, value, '', callback); -} - -async function runWithSettingInternal(key: string, value: string | boolean | undefined, prefix: string, callback: () => Promise): Promise { - const oldValue: string | boolean | undefined = getGlobalSetting(key, prefix); - try { - await updateGlobalSetting(key, value, prefix); - await callback(); - } finally { - await updateGlobalSetting(key, oldValue, prefix); - } -} diff --git a/test/test.code-workspace b/test/test.code-workspace deleted file mode 100644 index d1d77c70e..000000000 --- a/test/test.code-workspace +++ /dev/null @@ -1,8 +0,0 @@ -{ - "folders": [ - { - "path": "../testWorkspace" - } - ], - "settings": {} -} diff --git a/test/timeout.test.ts b/test/timeout.test.ts deleted file mode 100644 index f155a5cb4..000000000 --- a/test/timeout.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { rejectOnTimeout, valueOnTimeout } from '../extension.bundle'; - -suite("timeout Tests", () => { - suite("rejectOnTimeout", () => { - - test("executes synchronously", async () => { - let executed: boolean = false; - - await rejectOnTimeout(1, () => { - executed = true; - }); - - assert.equal(executed, true); - }); - - test("executes synchronously in promise", async () => { - let executed = false; - - await rejectOnTimeout(1, () => { - return new Promise((resolve, _reject) => { - executed = true; - resolve(); - }); - }); - - assert.equal(executed, true); - }); - - test("executes asynchnously before time-out", async () => { - let executed = false; - - await rejectOnTimeout(1000, () => { - return new Promise((resolve, _reject) => { - setTimeout(() => { executed = true; resolve(); }, 1); - }); - }); - assert.equal(executed, true); - }); - - test("timed out", async () => { - let executed = false; - - try { - await rejectOnTimeout(1, async () => { - await new Promise((resolve, _reject) => { - setTimeout(() => { executed = true; resolve(); }, 1000); - }); - }); - - assert.fail(null, null, "Expected exception"); - } catch (error) { - } - - assert.equal(executed, false); - }); - - test("throws before time-out", async () => { - const executed = false; - let error: Error = new Error("I haven't thrown up yet"); - - try { - await rejectOnTimeout(1000, async () => { - await new Promise((_resolve, _reject) => { - throw new Error("I threw up"); - }); - }); - } catch (err) { - error = err; - } - - assert.equal(executed, false); - assert.equal(error.message, "I threw up"); - }); - }); - - suite("valueOnTimeout", () => { - - test("executed", async () => { - const value = await valueOnTimeout(1000, 123, async () => { - return await new Promise((resolve, _reject) => { - setTimeout(() => { resolve(-123); }, 1); - }); - }); - - assert.equal(value, -123); - }); - - test("timed out", async () => { - const value = await valueOnTimeout(1, 123, async () => { - return await new Promise((resolve, _reject) => { - setTimeout(() => { resolve(-123); }, 1000); - }); - }); - - assert.equal(value, 123); - }); - - test("reject", async () => { - let error; - try { - await valueOnTimeout(1000, 123, async () => { - return await new Promise((_resolve, reject) => { - setTimeout(() => { reject(new Error("rejected")); }, 1); - }); - }); - } catch (err) { - error = err; - } - - assert.equal(error && error.message, "rejected"); - }); - }); - -}); diff --git a/test/unit/DocDBUtils.test.ts b/test/unit/DocDBUtils.test.ts deleted file mode 100644 index 0fafd95cf..000000000 --- a/test/unit/DocDBUtils.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { describe, it } from 'mocha'; -import { sanitizeId } from "../../src/docdb/tree/DocDBUtils"; - -describe("DocDBUtils", function () { - it("Replaces + with whitespace", function () { - const id = "a+b+c"; - const sanitizedId = sanitizeId(id); - assert.strictEqual(sanitizedId, "a b c"); - }); -}); diff --git a/test/unit/getClientConfig.test.ts b/test/unit/getClientConfig.test.ts deleted file mode 100644 index 33f8883e1..000000000 --- a/test/unit/getClientConfig.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { describe, it } from 'mocha'; -import { postgresDefaultPort } from '../../src/constants'; -import { PostgresServerType } from '../../src/postgres/abstract/models'; -import { getClientConfigs } from '../../src/postgres/getClientConfig'; -import { ParsedPostgresConnectionString } from '../../src/postgres/postgresConnectionStrings'; - -describe("getClientConfig Tests", () => { - describe("in subscription", () => { - it("Password only", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - user: "fake_user", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - // Cannot test null/undefined host because if it is the case, the code has thrown much earlier when constructing the ParsedPostgresConnectionString object. - - it("Password only - Missing port", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - user: "fake_user", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - assert(clientConfigs.password?.port === parseInt(postgresDefaultPort), "Should fallback to default port"); - }); - - it("Password only - missing username", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - password: "fake_password", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("No credential", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - user: "fake_user", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, true, databaseName); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad only - Flexible server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Flexible, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd !== undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad and password - Flexible server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database", - user: "fake_user", - password: "fake_password", - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Flexible, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password !== undefined); - assert(clientConfigs.azureAd !== undefined); - assert(clientConfigs.connectionString === undefined); - }); - - it("Aad only - Single server", async () => { - const parsedConnectionString = new ParsedPostgresConnectionString( - "", - { - host: "fake_host.com", - port: "1234", - database: "fake_database" - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs( - parsedConnectionString, - PostgresServerType.Single, - true, - databaseName, - "fake_azureAd_userId", - async () => "fake_token" - ); - assert(clientConfigs.password === undefined); - assert(clientConfigs.azureAd === undefined); - assert(clientConfigs.connectionString === undefined); - }); - }); - - describe("in attachment", () => { - it("Connection string only", async () => { - const rawConnectionString = "postgres://fake_connection_string"; - const parsedConnectionString = new ParsedPostgresConnectionString( - rawConnectionString, - { - host: "fake_host", - database: null - } - ); - const databaseName = "fake_database_2"; - - const clientConfigs = await getClientConfigs(parsedConnectionString, PostgresServerType.Flexible, false, databaseName); - assert(clientConfigs.connectionString !== undefined); - }); - }); -}); diff --git a/test/util/getIp.test.ts b/test/util/getIp.test.ts deleted file mode 100644 index 3e2b0cbc1..000000000 --- a/test/util/getIp.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { createTestActionContext } from '@microsoft/vscode-azext-dev'; -import * as assert from 'assert'; -import { isIPv4 } from 'net'; -import { getPublicIpv4, isIpInRanges } from '../../extension.bundle'; - -suite("getPublicIpv4", () => { - test("get IP", async () => { - try { - const context = await createTestActionContext(); - const ip = await getPublicIpv4(context); - assert(isIPv4(ip), "IP address isn't v4"); - } catch (error) { - assert(false, error.message ?? "Fail to get IP address"); - } - }); -}); - -suite("isIpInRanges", function () { - const ip = "12.34.56.78"; - test("Includes ip at start", function () { - const ranges = [{ startIpAddress: "12.34.56.78", endIpAddress: "12.34.56.80" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Includes ip at end", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.78" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Includes ip in range", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.80" }]; - assert(isIpInRanges(ip, ranges)); - }); - test("Excludes ip before start", function () { - const ranges = [{ startIpAddress: "12.34.56.80", endIpAddress: "12.34.56.80" }]; - assert(!isIpInRanges(ip, ranges)); - }); - test("Excludes ip after end", function () { - const ranges = [{ startIpAddress: "12.34.56.76", endIpAddress: "12.34.56.76" }]; - assert(!isIpInRanges(ip, ranges)); - }); -}); diff --git a/test/util/setEnvironmentVariables.test.ts b/test/util/setEnvironmentVariables.test.ts deleted file mode 100644 index 333a6803b..000000000 --- a/test/util/setEnvironmentVariables.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { isWindows } from '../../extension.bundle'; -import { setEnvironmentVariables } from './setEnvironmentVariables'; - -suite("setEnvironmentVariables (test util)", () => { - test("restore", () => { - const currentPath = process.env.PATH; - const dispose = setEnvironmentVariables({ PATH: "new path" }); - - assert.equal(process.env.PATH, 'new path'); - - dispose.dispose(); - - assert.equal(process.env.PATH, currentPath); - }); - - test("different casings (Windows)", () => { - if (isWindows) { - const currentPath = process.env.paTH; - const dispose = setEnvironmentVariables({ PAth: "new path" }); - - assert.equal(process.env.path, 'new path'); - assert.equal(process.env.PATH, 'new path'); - - dispose.dispose(); - - assert.equal(process.env.path, currentPath); - assert.equal(process.env.PATH, currentPath); - } - }); -}); diff --git a/test/util/setEnvironmentVariables.ts b/test/util/setEnvironmentVariables.ts deleted file mode 100644 index 7dc468729..000000000 --- a/test/util/setEnvironmentVariables.ts +++ /dev/null @@ -1,35 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IDisposable } from "../../extension.bundle"; - -/** - * Add a set of environment variables, and return to the previous values after disposing the result - */ -export function setEnvironmentVariables(env: { [key: string]: string }): IDisposable { - const setRestoreEnv = new SetRestoreEnv(); - setRestoreEnv.set(env); - return setRestoreEnv; -} - -class SetRestoreEnv implements IDisposable { - private _previousValues: { [key: string]: string } = {}; - - public set(env: { [key: string]: string }): void { - for (const key of Object.keys(env || {})) { - [this._previousValues[key], process.env[key]] = [process.env[key]!, env[key]]; - } - } - - public restore(): void { - for (const key of Object.keys(this._previousValues)) { - process.env[key] = this._previousValues[key]; - } - } - - public dispose(): void { - this.restore(); - } -} diff --git a/test/wrapError.test.ts b/test/wrapError.test.ts deleted file mode 100644 index 3663aa7ee..000000000 --- a/test/wrapError.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import * as os from 'os'; -import { wrapError } from '../extension.bundle'; - -suite("wrapError", () => { - test("just outer string", () => { - const wrapped = wrapError('Outer error'); - assert(typeof wrapped === 'string'); - assert.equal(wrapped, 'Outer error'); - }); - - test("just outer error", () => { - const wrapped = wrapError(new Error('Outer error')); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, 'Outer error'); - }); - - test("just inner", () => { - const wrapped = wrapError(undefined, 'Inner error'); - assert(typeof wrapped === 'string'); - assert.equal(wrapped, 'Inner error'); - }); - - test("outer string, inner string", () => { - const wrapped = wrapError('Outer error.', 'Inner error.'); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer error, inner string", () => { - const wrapped = wrapError(new Error('Outer error.'), 'Inner error.'); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer error, inner error", () => { - const wrapped = wrapError(new Error('Outer error.'), new Error('Inner error.')); - assert(wrapped instanceof Error); - assert.equal(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); - - test("outer string, inner error", () => { - const wrapped = wrapError('Outer error.', new Error('Inner error.')); - assert(wrapped instanceof Error); - assert(parseError(wrapped).message, `Outer error.${os.EOL}Inner error.`); - }); -}); From 9681a9f97be6abf5378545e8238352ab3096fa60 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Wed, 22 Nov 2023 07:52:56 +0200 Subject: [PATCH 25/33] squash! --- .vscode/extensions.json | 8 - .vscode/launch.json | 145 - .vscode/settings.json | 25 - .vscode/tasks.json | 23 - CHANGELOG.md | 619 +- LICENSE.md | 42 +- NOTICE.html | 5206 +++++++-------- README.md | 208 +- SECURITY.md | 2 +- SUPPORT.md | 3 +- Source/AzureDBExperiences.ts | 250 +- Source/DatabasesFileSystem.ts | 147 +- Source/ParsedConnectionString.ts | 36 +- Source/azureAccountUtils.ts | 27 +- Source/constants.ts | 133 +- Source/extension.ts | 592 +- Source/extensionVariables.ts | 61 +- Source/getExtensionApi.ts | 41 +- Source/vscode-cosmosdb.api.d.ts | 154 +- Source/vscode-cosmosdbgraph.api.d.ts | 26 +- build/vscode-languageserver-files-stub.js | 52 +- grammar/JavaScript.tmLanguage.json | 7420 ++++++++++----------- grammar/Readme.md | 9 +- grammar/configuration.json | 90 +- 24 files changed, 7856 insertions(+), 7463 deletions(-) delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 41fe51ef5..000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "recommendations": [ - "dbaeumer.vscode-eslint", - "ms-vscode.azure-account", - "ms-azuretools.vscode-azureresourcegroups", - "mike-lischke.vscode-antlr4" - ] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 626d91e57..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,145 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -{ - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}", - "env": { - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "" - } - }, - { - "name": "Launch Extension + Host", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionDevelopmentPath=${workspaceFolder}/../vscode-azureresourcegroups" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}", - "env": { - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "" - } - }, - { - "name": "Launch Extension (webpack)", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], - "preLaunchTask": "npm: webpack", - "env": { - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "", - "DEBUG_WEBPACK": "1" - } - }, - { - "name": "Launch Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/index", - "${workspaceFolder}/test/test.code-workspace" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}", - "env": { - "MOCHA_grep": "", // RegExp of tests to run (empty for all) - "MOCHA_timeout": "0", // Disable time-outs - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "", - "ENABLE_LONG_RUNNING_TESTS": "" - } - }, - { - "name": "Launch Tests (webpack)", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/dist/test/index", - "${workspaceFolder}/test/test.code-workspace" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], - "preLaunchTask": "npm: webpack", - "env": { - "MOCHA_grep": "", // RegExp of tests to run (empty for all) - "MOCHA_timeout": "0", // Disable time-outs - "DEBUGTELEMETRY": "v", - "NODE_DEBUG": "", - "DEBUG_WEBPACK": "1", - "ENABLE_LONG_RUNNING_TESTS": "" - } - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Language Server", - "protocol": "inspector", - "port": 6005, - "sourceMaps": true, - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ] - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Extension Host", - "protocol": "inspector", - "port": 5870, - "sourceMaps": true, - "restart": true, - "outFiles": [ - "${workspaceFolder}/out/src" - ] - }, - { - // INSTRUCTIONS - // 1) Point 'input' to a debugging input file and set "input" below to the file's path - // 2) *** IMPORTANT*** Make a whitespace change in mongo.g4 and then save it. This forces debugging info to be generated. - // If this works, you'll see a warning in the Output window. - // 3) Launch this configuration - // 4) See Debug Console output - // 5) In mongo.g4 file, in the editor context menu, you should see options for generating graphs - "name": "Debug Mongo grammar", - "type": "antlr-debug", - "request": "launch", - // This doesn't seem to work: "input": "${workspaceFolder}/${command:AskForTestInput}", - "input": "c:/temp/debugger-input.mongo", - "grammar": "grammar/mongo.g4", - "startRule": "mongoCommands", - "printParseTree": true, - "visualParseTree": true - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 52e1d220a..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, - "source.organizeImports": true - }, - "editor.detectIndentation": false, - "editor.formatOnSave": true, - "editor.insertSpaces": true, - "editor.tabSize": 4, - "files.insertFinalNewline": true, - "files.trimTrailingWhitespace": true, - "search.exclude": { - "out": true, - "**/node_modules": true, - ".vscode-test": true - }, - "typescript.preferences.importModuleSpecifier": "relative", - "typescript.tsdk": "node_modules/typescript/lib", - "antlr4.generation": { - // Settings for "ANTLR4 grammar syntax support" extension - "mode": "internal", - "listeners": true, - "visitors": false - } -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 5c4125cd9..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "compile", - "group": { - "kind": "build", - "isDefault": true - }, - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "problemMatcher": "$tsc-watch" - }, - { - "type": "npm", - "script": "lint", - "problemMatcher": "$eslint-stylish" - } - ] -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eab12dcc..c7a35d26b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,403 +2,632 @@ ## 0.20.0 -This release adds the initial Azure AD authentication support for PostgreSQL flexible database servers and fixed various bugs. See [0.20.0](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.20.0+is%3Aclosed+) for all closed issues. +This release adds the initial Azure AD authentication support for PostgreSQL +flexible database servers and fixed various bugs. See +[0.20.0](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.20.0+is%3Aclosed+) +for all closed issues. ### Breaking change -- The extension is migrated to use vscode secretStorage module for storing user credentials [#2137](https://github.com/microsoft/vscode-cosmosdb/issues/2137). If you have local attachments that are broken due to this change, please re-attach them. -- The CosmosDB Graph extension has been removed from the marketplace. Attempting to open the graph explorer will open a documentation suggesting alternative tools for viewing graphs [#2086](https://github.com/microsoft/vscode-cosmosdb/issues/2086). +- The extension is migrated to use vscode secretStorage module for storing + user credentials + [#2137](https://github.com/microsoft/vscode-cosmosdb/issues/2137). If you + have local attachments that are broken due to this change, please re-attach + them. +- The CosmosDB Graph extension has been removed from the marketplace. + Attempting to open the graph explorer will open a documentation suggesting + alternative tools for viewing graphs + [#2086](https://github.com/microsoft/vscode-cosmosdb/issues/2086). ### Added -- The extension now supports connecting to PostgreSQL flexible database server as Azure AD users. Read this [wiki](https://aka.ms/postgresql-passwordless-wiki) to learn more. +- The extension now supports connecting to PostgreSQL flexible database server + as Azure AD users. Read this + [wiki](https://aka.ms/postgresql-passwordless-wiki) to learn more. ## 0.19.4 - 2023-05-17 ### Added -* Add support for the upcoming Azure Resources Focus feature + +- Add support for the upcoming Azure Resources Focus feature ## 0.19.3 - 2023-02-15 ### Added -* Forward compatibility with Azure Resources API v2 @alexweininger in [#2095](https://github.com/microsoft/vscode-cosmosdb/pull/2095) + +- Forward compatibility with Azure Resources API v2 @alexweininger in + [#2095](https://github.com/microsoft/vscode-cosmosdb/pull/2095) ### Changed -* Remove Preview label for Postgres Flexible by @tonybaloney in [#2058](https://github.com/microsoft/vscode-cosmosdb/pull/2058) -* Fix revealing attached database by @alexweininger in [#2092](https://github.com/microsoft/vscode-cosmosdb/pull/2092) + +- Remove Preview label for Postgres Flexible by @tonybaloney in + [#2058](https://github.com/microsoft/vscode-cosmosdb/pull/2058) +- Fix revealing attached database by @alexweininger in + [#2092](https://github.com/microsoft/vscode-cosmosdb/pull/2092) ### Engineering -* Remove version checker action by @alexweininger in [#2046](https://github.com/microsoft/vscode-cosmosdb/pull/2046) -* Replace public-ip with our own util to fix CVE-2022-33987 by @alexweininger in [#2048](https://github.com/microsoft/vscode-cosmosdb/pull/2048) -* Migrate to vscode-azext-dev by @alexweininger in [#2050](https://github.com/microsoft/vscode-cosmosdb/pull/2050) -* Update AppInsights key by @bwateratmsft in [#2052](https://github.com/microsoft/vscode-cosmosdb/pull/2052) -* Add post release version bumper by @alexweininger in [#2053](https://github.com/microsoft/vscode-cosmosdb/pull/2053) -* Use shared Azure Id parsing utils by @alexweininger in [#2054](https://github.com/microsoft/vscode-cosmosdb/pull/2054) -* Rename info-needed-closer by @bwateratmsft in [#2056](https://github.com/microsoft/vscode-cosmosdb/pull/2056) -* Move workflow from root to workflows folder by @alexweininger in [#2057](https://github.com/microsoft/vscode-cosmosdb/pull/2057) -* Change filter for treeItemPicker by @nturinski in [#2063](https://github.com/microsoft/vscode-cosmosdb/pull/2063) -* Finalize CodeQL settings by @bwateratmsft in [#2068](https://github.com/microsoft/vscode-cosmosdb/pull/2068) -* Fix readme badges by @bwateratmsft in [#2070](https://github.com/microsoft/vscode-cosmosdb/pull/2070) -* Skip test suite to enable CodeQL build by @nturinski in [#2081](https://github.com/microsoft/vscode-cosmosdb/pull/2081) -* Add .nvmrc file by @alexweininger in [#2085](https://github.com/microsoft/vscode-cosmosdb/pull/2085) -* Use updated AzExtTreeFileSystem by @alexweininger in [#2094](https://github.com/microsoft/vscode-cosmosdb/pull/2094) + +- Remove version checker action by @alexweininger in + [#2046](https://github.com/microsoft/vscode-cosmosdb/pull/2046) +- Replace public-ip with our own util to fix CVE-2022-33987 by @alexweininger + in [#2048](https://github.com/microsoft/vscode-cosmosdb/pull/2048) +- Migrate to vscode-azext-dev by @alexweininger in + [#2050](https://github.com/microsoft/vscode-cosmosdb/pull/2050) +- Update AppInsights key by @bwateratmsft in + [#2052](https://github.com/microsoft/vscode-cosmosdb/pull/2052) +- Add post release version bumper by @alexweininger in + [#2053](https://github.com/microsoft/vscode-cosmosdb/pull/2053) +- Use shared Azure Id parsing utils by @alexweininger in + [#2054](https://github.com/microsoft/vscode-cosmosdb/pull/2054) +- Rename info-needed-closer by @bwateratmsft in + [#2056](https://github.com/microsoft/vscode-cosmosdb/pull/2056) +- Move workflow from root to workflows folder by @alexweininger in + [#2057](https://github.com/microsoft/vscode-cosmosdb/pull/2057) +- Change filter for treeItemPicker by @nturinski in + [#2063](https://github.com/microsoft/vscode-cosmosdb/pull/2063) +- Finalize CodeQL settings by @bwateratmsft in + [#2068](https://github.com/microsoft/vscode-cosmosdb/pull/2068) +- Fix readme badges by @bwateratmsft in + [#2070](https://github.com/microsoft/vscode-cosmosdb/pull/2070) +- Skip test suite to enable CodeQL build by @nturinski in + [#2081](https://github.com/microsoft/vscode-cosmosdb/pull/2081) +- Add .nvmrc file by @alexweininger in + [#2085](https://github.com/microsoft/vscode-cosmosdb/pull/2085) +- Use updated AzExtTreeFileSystem by @alexweininger in + [#2094](https://github.com/microsoft/vscode-cosmosdb/pull/2094) ### Dependencies -* Bump extension version post release by @alexweininger in [#2045](https://github.com/microsoft/vscode-cosmosdb/pull/2045) -* Bump moment from 2.29.2 to 2.29.4 by @dependabot in [#2049](https://github.com/microsoft/vscode-cosmosdb/pull/2049) -* Bump loader-utils from 1.4.0 to 1.4.2 by @dependabot in [#2077](https://github.com/microsoft/vscode-cosmosdb/pull/2077) -* Bump yargs-parser and yargs by @dependabot in [#2078](https://github.com/microsoft/vscode-cosmosdb/pull/2078) -* Bump decode-uri-component from 0.2.0 to 0.2.2 by @dependabot in [#2083](https://github.com/microsoft/vscode-cosmosdb/pull/2083) -* Bump qs from 6.10.1 to 6.11.0 by @dependabot in [#2084](https://github.com/microsoft/vscode-cosmosdb/pull/2084) -* Bump @xmldom/xmldom from 0.7.5 to 0.7.8 by @dependabot in [#2074](https://github.com/microsoft/vscode-cosmosdb/pull/2074) -* Bump flat and mocha by @dependabot in [#2088](https://github.com/microsoft/vscode-cosmosdb/pull/2088) -* Bump json5 from 1.0.1 to 1.0.2 by @dependabot in [#2089](https://github.com/microsoft/vscode-cosmosdb/pull/2089) + +- Bump extension version post release by @alexweininger in + [#2045](https://github.com/microsoft/vscode-cosmosdb/pull/2045) +- Bump moment from 2.29.2 to 2.29.4 by @dependabot in + [#2049](https://github.com/microsoft/vscode-cosmosdb/pull/2049) +- Bump loader-utils from 1.4.0 to 1.4.2 by @dependabot in + [#2077](https://github.com/microsoft/vscode-cosmosdb/pull/2077) +- Bump yargs-parser and yargs by @dependabot in + [#2078](https://github.com/microsoft/vscode-cosmosdb/pull/2078) +- Bump decode-uri-component from 0.2.0 to 0.2.2 by @dependabot in + [#2083](https://github.com/microsoft/vscode-cosmosdb/pull/2083) +- Bump qs from 6.10.1 to 6.11.0 by @dependabot in + [#2084](https://github.com/microsoft/vscode-cosmosdb/pull/2084) +- Bump @xmldom/xmldom from 0.7.5 to 0.7.8 by @dependabot in + [#2074](https://github.com/microsoft/vscode-cosmosdb/pull/2074) +- Bump flat and mocha by @dependabot in + [#2088](https://github.com/microsoft/vscode-cosmosdb/pull/2088) +- Bump json5 from 1.0.1 to 1.0.2 by @dependabot in + [#2089](https://github.com/microsoft/vscode-cosmosdb/pull/2089) ## 0.19.2 - 2022-06-30 ### Changed -- Update @vscode/extension-telemetry to 0.6.2 [#2042](https://github.com/microsoft/vscode-cosmosdb/pull/2042) + +- Update @vscode/extension-telemetry to 0.6.2 + [#2042](https://github.com/microsoft/vscode-cosmosdb/pull/2042) ## 0.19.1 - 2022-06-01 ### Changed -- Update @vscode/extension-telemetry to 0.5.2 [#2032](https://github.com/microsoft/vscode-cosmosdb/pull/2032) + +- Update @vscode/extension-telemetry to 0.5.2 + [#2032](https://github.com/microsoft/vscode-cosmosdb/pull/2032) ## 0.19.0 - 2022-05-24 -We've made some large design changes to the Azure extensions for VS Code. [View App Centric release notes](https://aka.ms/AzCode/AppCentric) +We've made some large design changes to the Azure extensions for VS Code. +[View App Centric release notes](https://aka.ms/AzCode/AppCentric) + ### Changed -- Minimum version of VS Code is now 1.57.0 + +- Minimum version of VS Code is now 1.57.0 ## 0.18.1 - 2021-08-11 + ### [Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/32?closed=1) -- Fixed the ETIMEDOUT issue when signing into a PostgreSQL Flexible server on multiple machines + +- Fixed the ETIMEDOUT issue when signing into a PostgreSQL Flexible server on + multiple machines ## 0.18.0 - 2021-07-21 + ### Added -- Postgres Flexible Servers (Preview) includes support for Databases, Functions and Stored Procedures + +- Postgres Flexible Servers (Preview) includes support for Databases, + Functions and Stored Procedures ### Changed -- Postgres Single Server defaults to version "11" + +- Postgres Single Server defaults to version "11" ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/26?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/26?closed=1) ## 0.17.0 - 2021-06-22 + ### Added -- SKU type option is now available while creating PostgreSQL servers -- Option to select either "Provisioned throughput" or "Serverless" model while creating CosmosDB accounts + +- SKU type option is now available while creating PostgreSQL servers +- Option to select either "Provisioned throughput" or "Serverless" model while + creating CosmosDB accounts ### Changed -- Icons updated to match VS Code's theme. Install new product icon themes [here](https://marketplace.visualstudio.com/search?term=tag%3Aproduct-icon-theme&target=VSCode) + +- Icons updated to match VS Code's theme. Install new product icon themes + [here](https://marketplace.visualstudio.com/search?term=tag%3Aproduct-icon-theme&target=VSCode) ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/30?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/30?closed=1) ## 0.16.0 - 2021-02-23 + ### Added -- Now depends on the "Azure Resources" extension, which provides a "Resource Groups" and "Help and Feedback" view -- Grouped items in all context menus to improve access and readability -- "Attached Emulator..." option added to Attach Database Accounts context menu + +- Now depends on the "Azure Resources" extension, which provides a "Resource + Groups" and "Help and Feedback" view +- Grouped items in all context menus to improve access and readability +- "Attached Emulator..." option added to Attach Database Accounts context menu ### Changed -- "Report an Issue" button was removed from errors. Use the "Help and Feedback" view or command palette instead + +- "Report an Issue" button was removed from errors. Use the "Help and + Feedback" view or command palette instead ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/29?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/29?closed=1) ## 0.15.1 - 2020-12-04 + ### Added -- Newly created Azure CosmosDB - MongoDB servers default to version “3.6” + +- Newly created Azure CosmosDB - MongoDB servers default to version “3.6” ### Changed -- Minimum version of VS Code is now 1.48.0 -- Improved extension activation time (by switching to the azure-sdk-for-js) + +- Minimum version of VS Code is now 1.48.0 +- Improved extension activation time (by switching to the azure-sdk-for-js) ### Fixed -- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/25?closed=1) + +- [Bugs Fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/25?closed=1) ## 0.15.0 - 2020-09-15 + ### Added -- Attach PostgreSQL servers by connection string -- PostgreSQL support for integration with App Service extension + +- Attach PostgreSQL servers by connection string +- PostgreSQL support for integration with App Service extension ### Changed -- PostgreSQL server defaults to version "10" + +- PostgreSQL server defaults to version "10" ### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.15.0+is%3Aclosed) + +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.15.0+is%3Aclosed) ## 0.14.0 - 2020-07-14 + ### Added -- Use the setting "azureDatabases.batchSize" to configure the Mongo "DBQuery.shellBatchSize" attribute and the batch size when loading children in the tree view. -- Create and edit stored procedures in PostgreSQL. NOTE: only applies to PostgreSQL server versions 11 and above. + +- Use the setting "azureDatabases.batchSize" to configure the Mongo + "DBQuery.shellBatchSize" attribute and the batch size when loading children + in the tree view. +- Create and edit stored procedures in PostgreSQL. NOTE: only applies to + PostgreSQL server versions 11 and above. ### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.14.0+is%3Aclosed) + +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.14.0+is%3Aclosed) ### Changed -- Results from executing most Mongo commands open in a single read-only editor. + +- Results from executing most Mongo commands open in a single read-only + editor. ## 0.13.0 - 2020-05-28 -In this release, we're rebranding the Cosmos DB Extension to Azure Databases to expand our database support beyond just Cosmos DB. This release also marks the first new database engine: PostgreSQL with other database engines coming later this year. + +In this release, we're rebranding the Cosmos DB Extension to Azure Databases to +expand our database support beyond just Cosmos DB. This release also marks the +first new database engine: PostgreSQL with other database engines coming later +this year. + ### Added -- PostgreSQL support - - Create and view PostgreSQL servers, databases, and functions. - - Create, edit, and execute PostgreSQL queries + +- PostgreSQL support + - Create and view PostgreSQL servers, databases, and functions. + - Create, edit, and execute PostgreSQL queries ### Fixed -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.13.0+is%3Aclosed) + +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.13.0+is%3Aclosed) ### Changed -- Viewing and querying Azure Cosmos DB graphs has been moved to a separate graph-specific extension, [vscode-cosmosdbgraph](https://github.com/microsoft/vscode-cosmosdbgraph) + +- Viewing and querying Azure Cosmos DB graphs has been moved to a separate + graph-specific extension, + [vscode-cosmosdbgraph](https://github.com/microsoft/vscode-cosmosdbgraph) ## 0.12.2 - 2020-03-10 + ### Fixed -- Language client is not ready yet [#1334](https://github.com/microsoft/vscode-cosmosdb/issues/1334) + +- Language client is not ready yet + [#1334](https://github.com/microsoft/vscode-cosmosdb/issues/1334) ## 0.12.1 - 2020-01-22 + ### Fixed -- When updating a Mongo document, the operation would fail with the following error: `update operation document must contain atomic operators.` [#1298](https://github.com/microsoft/vscode-cosmosdb/issues/1298) -- When importing a `.json` document into a Mongo collection, it would throw the following error: `Error: r.insertedIds is not iterable` [#1307](https://github.com/microsoft/vscode-cosmosdb/issues/1307) + +- When updating a Mongo document, the operation would fail with the following + error: `update operation document must contain atomic operators.` + [#1298](https://github.com/microsoft/vscode-cosmosdb/issues/1298) +- When importing a `.json` document into a Mongo collection, it would throw + the following error: `Error: r.insertedIds is not iterable` + [#1307](https://github.com/microsoft/vscode-cosmosdb/issues/1307) ## 0.12.0 - 2020-01-16 + ### Added -- Support for Private Endpoint Connections -- Collapse All button for Cosmos DB explorer + +- Support for Private Endpoint Connections +- Collapse All button for Cosmos DB explorer ### Fixed -- When using `find()` in MongoScrapbooks, it would not work properly with chained commands [#981](https://github.com/microsoft/vscode-cosmosdb/issues/981) -- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/18?closed=1) + +- When using `find()` in MongoScrapbooks, it would not work properly with + chained commands + [#981](https://github.com/microsoft/vscode-cosmosdb/issues/981) +- [Bugs fixed](https://github.com/microsoft/vscode-cosmosdb/milestone/18?closed=1) ## 0.11.0 - 2019-09-03 + ### Added -- Add `mongo.shell.args` setting to allow passing arguments to mongo shell [#1104](https://github.com/Microsoft/vscode-cosmosdb/issues/1104), [#1126](https://github.com/Microsoft/vscode-cosmosdb/issues/1126) + +- Add `mongo.shell.args` setting to allow passing arguments to mongo shell + [#1104](https://github.com/Microsoft/vscode-cosmosdb/issues/1104), + [#1126](https://github.com/Microsoft/vscode-cosmosdb/issues/1126) ### Changed -- Due to a change in the Azure Cosmos DB Emulator, users must explicitly enable the Mongo DB port when starting the emulator. Updated error messages to point to debugging tips at https://aka.ms/AA5zah5. [#1137](https://github.com/microsoft/vscode-cosmosdb/issues/1137), [#1000](https://github.com/microsoft/vscode-cosmosdb/issues/1000) + +- Due to a change in the Azure Cosmos DB Emulator, users must explicitly + enable the Mongo DB port when starting the emulator. Updated error messages + to point to debugging tips at https://aka.ms/AA5zah5. + [#1137](https://github.com/microsoft/vscode-cosmosdb/issues/1137), + [#1000](https://github.com/microsoft/vscode-cosmosdb/issues/1000) ### Fixed -- Better shell error handling, add mongo.shell.args setting [#1101](https://github.com/Microsoft/vscode-cosmosdb/issues/1101), [#1092](https://github.com/Microsoft/vscode-cosmosdb/issues/1092), [#1071](https://github.com/Microsoft/vscode-cosmosdb/issues/1071), [#988](https://github.com/Microsoft/vscode-cosmosdb/issues/988), [#838](https://github.com/Microsoft/vscode-cosmosdb/issues/838), [#820](https://github.com/Microsoft/vscode-cosmosdb/issues/820) -- Increase mongo.shell.timeout default value from 5 to 30 [#1115](https://github.com/Microsoft/vscode-cosmosdb/issues/1115) -- Fix document save prompt message [#1021](https://github.com/Microsoft/vscode-cosmosdb/issues/1021) + +- Better shell error handling, add mongo.shell.args setting + [#1101](https://github.com/Microsoft/vscode-cosmosdb/issues/1101), + [#1092](https://github.com/Microsoft/vscode-cosmosdb/issues/1092), + [#1071](https://github.com/Microsoft/vscode-cosmosdb/issues/1071), + [#988](https://github.com/Microsoft/vscode-cosmosdb/issues/988), + [#838](https://github.com/Microsoft/vscode-cosmosdb/issues/838), + [#820](https://github.com/Microsoft/vscode-cosmosdb/issues/820) +- Increase mongo.shell.timeout default value from 5 to 30 + [#1115](https://github.com/Microsoft/vscode-cosmosdb/issues/1115) +- Fix document save prompt message + [#1021](https://github.com/Microsoft/vscode-cosmosdb/issues/1021) ## 0.10.2 - 2019-05-01 + ### Fixed -- Handle opening resources to use native vscode APIs -- Running the extension in older versions of VS Code -- Report an issue opening a blank webpage due to a large stack frame + +- Handle opening resources to use native vscode APIs +- Running the extension in older versions of VS Code +- Report an issue opening a blank webpage due to a large stack frame ## 0.10.1 - 2019-03-26 + ### Added -- Wizards are more informative and allow you to redo some steps + +- Wizards are more informative and allow you to redo some steps ### Fixed -- Graph views moved from using previewHtml (deprecated) to Webview API + +- Graph views moved from using previewHtml (deprecated) to Webview API ## 0.10.0 - 2019-02-13 + ### Added -* Improved startup and installation performance + +- Improved startup and installation performance ### Fixed -* Accounts created in portal are not recognized as graph/mongo by the extension [#1018](https://github.com/Microsoft/vscode-cosmosdb/issues/1018) -* Confusing error message when running 'Import Document into a Collection' with no Workspace opened [#961](https://github.com/Microsoft/vscode-cosmosdb/issues/961) -* Improve emulator connection error messages [#1016](https://github.com/Microsoft/vscode-cosmosdb/issues/1016) + +- Accounts created in portal are not recognized as graph/mongo by the + extension [#1018](https://github.com/Microsoft/vscode-cosmosdb/issues/1018) +- Confusing error message when running 'Import Document into a Collection' + with no Workspace opened + [#961](https://github.com/Microsoft/vscode-cosmosdb/issues/961) +- Improve emulator connection error messages + [#1016](https://github.com/Microsoft/vscode-cosmosdb/issues/1016) ## 0.9.1 - 2018-11-28 + ### Added -- API support for integration with [App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) -- Multiple documents, collections, or stored procedures can be viewed/edited at once (thanks [@tec-goblin](https://github.com/tec-goblin)) + +- API support for integration with + [App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) +- Multiple documents, collections, or stored procedures can be viewed/edited + at once (thanks [@tec-goblin](https://github.com/tec-goblin)) ### [Fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.9.1+label%3Abug+is%3Aclosed) -- Refresh button doesn't refresh attached accounts [#904](https://github.com/Microsoft/vscode-cosmosdb/issues/904) -- Some scrapbook parse errors were causing an error alert [#959](https://github.com/Microsoft/vscode-cosmosdb/pull/959) -- Downgrade event-stream version due to [event-stream#116](https://github.com/dominictarr/event-stream/issues/116) + +- Refresh button doesn't refresh attached accounts + [#904](https://github.com/Microsoft/vscode-cosmosdb/issues/904) +- Some scrapbook parse errors were causing an error alert + [#959](https://github.com/Microsoft/vscode-cosmosdb/pull/959) +- Downgrade event-stream version due to + [event-stream#116](https://github.com/dominictarr/event-stream/issues/116) ## 0.9.0 - 2018-11-05 + ### Added -- Mongo - - Support for [ObjectId, ISODate](https://github.com/Microsoft/vscode-cosmosdb/issues/769) and [regular expression](https://github.com/Microsoft/vscode-cosmosdb/issues/786) [(/pattern/flag)](https://github.com/Microsoft/vscode-cosmosdb/issues/667) syntax in the scrapbook - - Support for [method chaining](https://github.com/Microsoft/vscode-cosmosdb/issues/785). - - Ability to [change timeout](https://github.com/Microsoft/vscode-cosmosdb/issues/809) for commands in scrapbook -- Support [importing documents](https://github.com/Microsoft/vscode-cosmosdb/issues/404) into CosmosDB and Mongo databases. -- Support for [soveriegn clouds](https://github.com/Microsoft/vscode-cosmosdb/commit/5b573f535cdeba109d7ff037b914575e0172c6bd) -- Support creation of fixed collections and graphs [#295](https://github.com/Microsoft/vscode-cosmosdb/issues/295) and [#504](https://github.com/Microsoft/vscode-cosmosdb/issues/504) + +- Mongo + - Support for + [ObjectId, ISODate](https://github.com/Microsoft/vscode-cosmosdb/issues/769) + and + [regular expression](https://github.com/Microsoft/vscode-cosmosdb/issues/786) + [(/pattern/flag)](https://github.com/Microsoft/vscode-cosmosdb/issues/667) + syntax in the scrapbook + - Support for + [method chaining](https://github.com/Microsoft/vscode-cosmosdb/issues/785). + - Ability to + [change timeout](https://github.com/Microsoft/vscode-cosmosdb/issues/809) + for commands in scrapbook +- Support + [importing documents](https://github.com/Microsoft/vscode-cosmosdb/issues/404) + into CosmosDB and Mongo databases. +- Support for + [soveriegn clouds](https://github.com/Microsoft/vscode-cosmosdb/commit/5b573f535cdeba109d7ff037b914575e0172c6bd) +- Support creation of fixed collections and graphs + [#295](https://github.com/Microsoft/vscode-cosmosdb/issues/295) and + [#504](https://github.com/Microsoft/vscode-cosmosdb/issues/504) ### Fixed -- Collections having two documents of the same id will render properly [#588](https://github.com/Microsoft/vscode-cosmosdb/issues/588) and [#892](https://github.com/Microsoft/vscode-cosmosdb/issues/892) -- Some UI fixes [#576](https://github.com/Microsoft/vscode-cosmosdb/issues/576) and [#873](https://github.com/Microsoft/vscode-cosmosdb/issues/873) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/milestone/16?closed=1) + +- Collections having two documents of the same id will render properly + [#588](https://github.com/Microsoft/vscode-cosmosdb/issues/588) and + [#892](https://github.com/Microsoft/vscode-cosmosdb/issues/892) +- Some UI fixes + [#576](https://github.com/Microsoft/vscode-cosmosdb/issues/576) and + [#873](https://github.com/Microsoft/vscode-cosmosdb/issues/873) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/milestone/16?closed=1) ### Thank you -A big thank you to the following contributors that helped make the extension even better! -- [Nicolas Kyriazopuolos-Panagiotopoulos @tec-goblin](https://github.com/tec-goblin): - - Updates to a collection now update the corresponding tree item [PR#856](https://github.com/Microsoft/vscode-cosmosdb/pull/856) - - Uploading a document by closing it no longer tries to update the closed editor [PR#818](https://github.com/Microsoft/vscode-cosmosdb/pull/818) - - Fixing tslint issues [PR#829](https://github.com/Microsoft/vscode-cosmosdb/pull/829) - - Use consistent language for various commands [PR#828](https://github.com/Microsoft/vscode-cosmosdb/pull/828) - - Fix some typos [PR#810](https://github.com/Microsoft/vscode-cosmosdb/pull/810) and [PR#816](https://github.com/Microsoft/vscode-cosmosdb/pull/816) -- [Nguyen Long Nhat @torn4dom4n](https://github.com/torn4dom4n), for updating our tasks [PR#887](https://github.com/Microsoft/vscode-cosmosdb/pull/887) + +A big thank you to the following contributors that helped make the extension +even better! + +- [Nicolas Kyriazopuolos-Panagiotopoulos @tec-goblin](https://github.com/tec-goblin): + - Updates to a collection now update the corresponding tree item + [PR#856](https://github.com/Microsoft/vscode-cosmosdb/pull/856) + - Uploading a document by closing it no longer tries to update the closed + editor [PR#818](https://github.com/Microsoft/vscode-cosmosdb/pull/818) + - Fixing tslint issues + [PR#829](https://github.com/Microsoft/vscode-cosmosdb/pull/829) + - Use consistent language for various commands + [PR#828](https://github.com/Microsoft/vscode-cosmosdb/pull/828) + - Fix some typos + [PR#810](https://github.com/Microsoft/vscode-cosmosdb/pull/810) and + [PR#816](https://github.com/Microsoft/vscode-cosmosdb/pull/816) +- [Nguyen Long Nhat @torn4dom4n](https://github.com/torn4dom4n), for updating + our tasks [PR#887](https://github.com/Microsoft/vscode-cosmosdb/pull/887) ## 0.8.0 - 2018-07-05 + ### Added -- Improved scrapbook experience with better error handling. We now [highlight errors on the scrapbook as you type](https://github.com/Microsoft/vscode-cosmosdb/issues/471)! -- See your [stored procedures for graph accounts](https://github.com/Microsoft/vscode-cosmosdb/issues/422) too! -- [Document labels](https://github.com/Microsoft/vscode-cosmosdb/issues/381) in the tree view are now more descriptive. + +- Improved scrapbook experience with better error handling. We now + [highlight errors on the scrapbook as you type](https://github.com/Microsoft/vscode-cosmosdb/issues/471)! +- See your + [stored procedures for graph accounts](https://github.com/Microsoft/vscode-cosmosdb/issues/422) + too! +- [Document labels](https://github.com/Microsoft/vscode-cosmosdb/issues/381) + in the tree view are now more descriptive. ### Fixed -- Scrapbook: can now parse commands with [single quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467) or [no quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467). Examples from the mongo docs should now work when directly pasted. -- Fewer timeout errors on [running commands in the emulator](https://github.com/Microsoft/vscode-cosmosdb/pull/731). -- We correctly parse [collection names with dots](https://github.com/Microsoft/vscode-cosmosdb/issues/666) -- Invalid database accounts will not [prevent the tree from loading](https://github.com/Microsoft/vscode-cosmosdb/issues/628) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?page=1&q=is%3Aissue+milestone%3A0.8.0+is%3Aclosed) + +- Scrapbook: can now parse commands with + [single quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467) or + [no quotes](https://github.com/Microsoft/vscode-cosmosdb/issues/467). + Examples from the mongo docs should now work when directly pasted. +- Fewer timeout errors on + [running commands in the emulator](https://github.com/Microsoft/vscode-cosmosdb/pull/731). +- We correctly parse + [collection names with dots](https://github.com/Microsoft/vscode-cosmosdb/issues/666) +- Invalid database accounts will not + [prevent the tree from loading](https://github.com/Microsoft/vscode-cosmosdb/issues/628) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?page=1&q=is%3Aissue+milestone%3A0.8.0+is%3Aclosed) ## 0.7.2 - 2018-06-08 ### Added -- [Support DNS Seedlist Connection Format](https://github.com/Microsoft/vscode-cosmosdb/pull/670) for mongo connection strings (mongodb+srv://). Thanks [@plusn-nuri](https://github.com/plusn-nuri)! + +- [Support DNS Seedlist Connection Format](https://github.com/Microsoft/vscode-cosmosdb/pull/670) + for mongo connection strings (mongodb+srv://). Thanks + [@plusn-nuri](https://github.com/plusn-nuri)! ### Fixed -- [Support for Extended JSON in scrapbook queries](https://github.com/Microsoft/vscode-cosmosdb/issues/621) -- [Updating mongo documents without an ObjectID in the ID field ](https://github.com/Microsoft/vscode-cosmosdb/issues/534) -- [Log of fixed bugs](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.7.2+is%3Aclosed) + +- [Support for Extended JSON in scrapbook queries](https://github.com/Microsoft/vscode-cosmosdb/issues/621) +- [Updating mongo documents without an ObjectID in the ID field ](https://github.com/Microsoft/vscode-cosmosdb/issues/534) +- [Log of fixed bugs](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A0.7.2+is%3Aclosed) ## 0.7.1 - 2018-05-10 ### [Fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.1%22+is%3Aclosed+label%3Abug) -- Fixed error "Unexpected Experience Value" when retrieving database accounts +- Fixed error "Unexpected Experience Value" when retrieving database accounts ## 0.7.0 - 2018-05-04 ### Added -- Mongo - - CodeLens support for scrapbook - - Execute all commands in a scrapbook, allowing you to use scrapbooks as scripts - - Support for ObjectIDs, ISODate, and extended JSON data types in document views -- SQL - - View, open, edit and update Stored Procedures +- Mongo + + - CodeLens support for scrapbook + - Execute all commands in a scrapbook, allowing you to use scrapbooks as + scripts + - Support for ObjectIDs, ISODate, and extended JSON data types in document + views -- Miscellaneous - - Error messages are now modal - - Open newly created docs in editor +- SQL + + - View, open, edit and update Stored Procedures + +- Miscellaneous + - Error messages are now modal + - Open newly created docs in editor ### Changed -- Moved Azure CosmosDB Explorer to new Azure view container instead of file explorer + +- Moved Azure CosmosDB Explorer to new Azure view container instead of file + explorer ### Fixed -- [Better error messages for connection strings](https://github.com/Microsoft/vscode-cosmosdb/pull/600) -- [Don't throw errors on dropping non-existent collections](https://github.com/Microsoft/vscode-cosmosdb/pull/541) -- [Errors no longer written to output in the middle of writing a scrapbook command](https://github.com/Microsoft/vscode-cosmosdb/issues/516) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.0%22+is%3Aclosed+label%3Abug) +- [Better error messages for connection strings](https://github.com/Microsoft/vscode-cosmosdb/pull/600) +- [Don't throw errors on dropping non-existent collections](https://github.com/Microsoft/vscode-cosmosdb/pull/541) +- [Errors no longer written to output in the middle of writing a scrapbook command](https://github.com/Microsoft/vscode-cosmosdb/issues/516) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.7.0%22+is%3Aclosed+label%3Abug) ## 0.6.0 - 2018-04-09 ### Added -- Mongo - - mongo.shell.path setting no longer required if shell is in system path - - Allow mongo.shell.path to be specified in workspace settings as well as user settings - - No longer asking for an id for new documents - - Connected database is now persisted between sessions - - Improvements to scrapbook setup and error handling +- Mongo -- Azure subscriptions - - New "filter" button on subscription nodes - - New "Open in Portal" menu item for subscriptions + - mongo.shell.path setting no longer required if shell is in system path + - Allow mongo.shell.path to be specified in workspace settings as well as + user settings + - No longer asking for an id for new documents + - Connected database is now persisted between sessions + - Improvements to scrapbook setup and error handling -- Miscellaneous - - New "Report an Issue" button on error dialogs +- Azure subscriptions + + - New "filter" button on subscription nodes + - New "Open in Portal" menu item for subscriptions + +- Miscellaneous + - New "Report an Issue" button on error dialogs ### Fixed -- [Allow access to multi-tenant mongo server](https://github.com/Microsoft/vscode-cosmosdb/issues/473) -- [Can only run the first command in a Mongo Scrapbook on Windows](https://github.com/Microsoft/vscode-cosmosdb/issues/386) -- [Projections Not Working In Mongo Scrapbooks](https://github.com/Microsoft/vscode-cosmosdb/issues/214) -- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.6.0%22+is%3Aclosed+label%3Abug) +- [Allow access to multi-tenant mongo server](https://github.com/Microsoft/vscode-cosmosdb/issues/473) +- [Can only run the first command in a Mongo Scrapbook on Windows](https://github.com/Microsoft/vscode-cosmosdb/issues/386) +- [Projections Not Working In Mongo Scrapbooks](https://github.com/Microsoft/vscode-cosmosdb/issues/214) +- [Additional bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.6.0%22+is%3Aclosed+label%3Abug) ## 0.5.1 - 2018-03-23 ### Fixed -- [Bug fixed](https://github.com/Microsoft/vscode-cosmosdb/issues/372) + +- [Bug fixed](https://github.com/Microsoft/vscode-cosmosdb/issues/372) + ## 0.5.0 - 2018-03-05 ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.5.0%22+is%3Aclosed+label%3Abug) +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.5.0%22+is%3Aclosed+label%3Abug) ### Added -- DocumentDB and Mongo - - Allow updating documents and collections re-opened from a previous VS Code session -- Mongo - - Delete databases +- DocumentDB and Mongo + - Allow updating documents and collections re-opened from a previous VS + Code session +- Mongo + - Delete databases ## 0.4.0 - 2018-01-25 + ### Added -- Attach to Cosmos DB emulator -- Run commands from the command palette + +- Attach to Cosmos DB emulator +- Run commands from the command palette ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.4.0%22+is%3Aclosed+label%3Abug) + +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.4.0%22+is%3Aclosed+label%3Abug) ## 0.3.0 - 2017-12-15 + ### Added -- Attach Cosmos DB accounts by connection string -- Graph: - - Customize the color and display text of vertices through VS Code [settings](README.md#graphSettings) - - By default display vertex IDs and labels and choose vertex color based on label - - Honor current VS Code theme + +- Attach Cosmos DB accounts by connection string +- Graph: + - Customize the color and display text of vertices through VS Code + [settings](README.md#graphSettings) + - By default display vertex IDs and labels and choose vertex color based + on label + - Honor current VS Code theme ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.3.0%22+is%3Aclosed+label%3Abug) + +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.3.0%22+is%3Aclosed+label%3Abug) ## 0.2.2 - 2017-12-04 + ### Added -- View, edit, and persist a Mongo collection -- Edit and persist the result of a Mongo command + +- View, edit, and persist a Mongo collection +- Edit and persist the result of a Mongo command ## 0.2.1 - 2017-11-16 + ### Fixed -- [Graph bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.1%22+is%3Aclosed+label%3Abug) - - Source to target arrows are backwards - - Side effects from executing a Gremlin query can occur twice - - Duplicate vertices can show up in graph viewer - - Query performance improved for large graphs + +- [Graph bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.1%22+is%3Aclosed+label%3Abug) + - Source to target arrows are backwards + - Side effects from executing a Gremlin query can occur twice + - Duplicate vertices can show up in graph viewer + - Query performance improved for large graphs ## 0.2.0 - 2017-11-10 + ### Added -- Graph: - - View/Create/Delete databases and graphs - - Click on a graph to visualize data - - Query graph using [Gremlin](https://docs.microsoft.com/azure/cosmos-db/gremlin-support) -- DocumentDB: - - View/Create/Delete databases, collections, and documents -- Mongo - - View documents in the explorer -- DocumentDB and Mongo: - - Click on a document to open in the editor - - Edit a document and persist changes to the cloud +- Graph: + - View/Create/Delete databases and graphs + - Click on a graph to visualize data + - Query graph using + [Gremlin](https://docs.microsoft.com/azure/cosmos-db/gremlin-support) +- DocumentDB: + - View/Create/Delete databases, collections, and documents +- Mongo + - View documents in the explorer +- DocumentDB and Mongo: + - Click on a document to open in the editor + - Edit a document and persist changes to the cloud ### Removed -- View Mongo documents in 'result.json' by clicking on a collection in the explorer -- Edit and persist the result of a Mongo scrapbook command + +- View Mongo documents in 'result.json' by clicking on a collection in the + explorer +- Edit and persist the result of a Mongo scrapbook command ### Fixed -- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.0%22+is%3Aclosed+label%3Abug) + +- [Bugs fixed](https://github.com/Microsoft/vscode-cosmosdb/issues?q=is%3Aissue+milestone%3A%220.2.0%22+is%3Aclosed+label%3Abug) ## 0.1.1 - 2017-09-19 + ### Changed -- Correctly set version to preview + +- Correctly set version to preview ## 0.1.0 - 2017-09-19 + ### Added -- Cosmos DB UI component (sash) -- Connect to local MongoDB -- Create Cosmos DB (with MongoDB adaptor) -- Connect to Cosmos DB via MongoDB adaptor -- Command to launch the `mongo` shell -- Rich MongoDB intellisense in scrapbooks + +- Cosmos DB UI component (sash) +- Connect to local MongoDB +- Create Cosmos DB (with MongoDB adaptor) +- Connect to Cosmos DB via MongoDB adaptor +- Command to launch the `mongo` shell +- Rich MongoDB intellisense in scrapbooks diff --git a/LICENSE.md b/LICENSE.md index 4b1ad51b2..21071075c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,21 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/NOTICE.html b/NOTICE.html index 7500e9041..3c64feaf0 100644 --- a/NOTICE.html +++ b/NOTICE.html @@ -1,186 +1,186 @@ - - - - NOTICES AND INFORMATION - - - -

NOTICES AND INFORMATION

-

Do Not Translate or Localize

-

- This software incorporates material from third parties. - Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, - or you may send a check or money order for US $5.00, including the product name, - the open source component name, platform, and version number, to: -

-
- Source Code Compliance Team
- Microsoft Corporation
- One Microsoft Way
- Redmond, WA 98052
- USA -
-

- Notwithstanding any other terms, you may reverse engineer this software to the extent - required to debug changes to any libraries licensed under the GNU Lesser General Public License. -

-
    -
  1. -
    - - tslib 1.14.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  2. -
  3. -
    - - tslib 2.1.0 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  4. -
  5. -
    - - tslib 2.3.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  6. -
  7. -
    - - tslib 2.4.0 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  8. -
  9. -
    - - tslib 2.6.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  10. -
  11. -
    - - tslib 2.6.2 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    -        Copyright (c) Microsoft Corporation.
    -
    -Permission to use, copy, modify, and/or distribute this software for any
    -purpose with or without fee is hereby granted.
    -
    -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    -PERFORMANCE OF THIS SOFTWARE.
    -        
    -
    -
  12. -
  13. -
    - - bson 1.1.4 - Apache-2.0 - -

    https://github.com/mongodb/js-bson#readme

    + + + + NOTICES AND INFORMATION + + + +

    NOTICES AND INFORMATION

    +

    Do Not Translate or Localize

    +

    + This software incorporates material from third parties. + Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, + or you may send a check or money order for US $5.00, including the product name, + the open source component name, platform, and version number, to: +

    +
    + Source Code Compliance Team
    + Microsoft Corporation
    + One Microsoft Way
    + Redmond, WA 98052
    + USA +
    +

    + Notwithstanding any other terms, you may reverse engineer this software to the extent + required to debug changes to any libraries licensed under the GNU Lesser General Public License. +

    +
      +
    1. +
      + + tslib 1.14.1 - 0BSD + +

      https://www.typescriptlang.org/

      +
      • Copyright (c) Microsoft Corporation
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    2. +
    3. +
      + + tslib 2.1.0 - 0BSD + +

      https://www.typescriptlang.org/

      +
      • Copyright (c) Microsoft Corporation
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    4. +
    5. +
      + + tslib 2.3.1 - 0BSD + +

      https://www.typescriptlang.org/

      +
      • Copyright (c) Microsoft Corporation
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    6. +
    7. +
      + + tslib 2.4.0 - 0BSD + +

      https://www.typescriptlang.org/

      +
      • Copyright (c) Microsoft Corporation
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    8. +
    9. +
      + + tslib 2.6.1 - 0BSD + +

      https://www.typescriptlang.org/

      +
      • Copyright (c) Microsoft Corporation
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    10. +
    11. +
      + + tslib 2.6.2 - 0BSD + +

      https://www.typescriptlang.org/

      +
      • Copyright (c) Microsoft Corporation
      +
      +        Copyright (c) Microsoft Corporation.
      +
      +Permission to use, copy, modify, and/or distribute this software for any
      +purpose with or without fee is hereby granted.
      +
      +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
      +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
      +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
      +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      +PERFORMANCE OF THIS SOFTWARE.
      +        
      +
      +
    12. +
    13. +
      + + bson 1.1.4 - Apache-2.0 + +

      https://github.com/mongodb/js-bson#readme

      • Copyright 2009 Google Inc.
      • Copyright (c) 2014, Facebook, Inc.
      • copyright (c) 2019 Denis Pushkarev
      • Copyright (c) 2008, Fair Oaks Labs, Inc.
      • -
      • Copyright Joyent, Inc. and other Node contributors.
      -
      +
    14. Copyright Joyent, Inc. and other Node contributors.
    15. +
                                                Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -382,18 +382,18 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    16. -
    17. -
      - - denque 1.4.1 - Apache-2.0 - -

      https://github.com/invertase/denque#readme

      -
      • Copyright (c) 2018 Mike Diarmid
      -
      +
      +        
      +
      +
    18. +
    19. +
      + + denque 1.4.1 - Apache-2.0 + +

      https://github.com/invertase/denque#readme

      +
      • Copyright (c) 2018 Mike Diarmid
      +
               Copyright (c) 2018 Mike Diarmid (Salakar) <mike.diarmid@gmail.com>
       
       Licensed under the Apache License, Version 2.0 (the "License");
      @@ -407,18 +407,18 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    20. -
    21. -
      - - jsbi 3.2.5 - Apache-2.0 - -

      https://github.com/GoogleChromeLabs/jsbi#readme

      - -
      +
      +        
      +
      +
    22. +
    23. +
      + + jsbi 3.2.5 - Apache-2.0 + +

      https://github.com/GoogleChromeLabs/jsbi#readme

      + +
                                                Apache License
                                  Version 2.0, January 2004
                               https://www.apache.org/licenses/
      @@ -595,19 +595,19 @@ 

      NOTICES AND INFORMATION

      of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS - -
      -
      -
    24. -
    25. -
      - - mongodb 3.6.10 - Apache-2.0 - -

      https://github.com/mongodb/node-mongodb-native

      + + +
      +
    26. +
    27. +
      + + mongodb 3.6.10 - Apache-2.0 + +

      https://github.com/mongodb/node-mongodb-native

      • (c) 2012-present MongoDB
      • -
      • (c) 2009-2012 Christian Amor Kvalheim
      -
      +
    28. (c) 2009-2012 Christian Amor Kvalheim
    29. +
               Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -808,18 +808,18 @@ 

      NOTICES AND INFORMATION

      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. -
      -
      -
    30. -
    31. -
      - - mongodb-extended-json 1.11.0 - Apache-2.0 - -

      http://github.com/mongodb-js/extended-json

      -
      • Copyright 2015 MongoDB Inc.
      -
      +   limitations under the License.
      +        
      +
      +
    32. +
    33. +
      + + mongodb-extended-json 1.11.0 - Apache-2.0 + +

      http://github.com/mongodb-js/extended-json

      +
      • Copyright 2015 MongoDB Inc.
      +
               Apache License
       Version 2.0, January 2004
       http://www.apache.org/licenses/
      @@ -1021,18 +1021,18 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -
      -
      -
    34. -
    35. -
      - - optional-require 1.1.8 - Apache-2.0 - -

      https://github.com/jchip/optional-require#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +
      +        
      +
      +
    36. +
    37. +
      + + optional-require 1.1.8 - Apache-2.0 + +

      https://github.com/jchip/optional-require#readme

      +
      • (c) Joel Chen (https://github.com/jchip)
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1129,18 +1129,18 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and -limitations under the License. -
      -
      -
    38. -
    39. -
      - - require-at 1.0.6 - Apache-2.0 - -

      https://github.com/jchip/require-at#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +limitations under the License.
      +        
      +
      +
    40. +
    41. +
      + + require-at 1.0.6 - Apache-2.0 + +

      https://github.com/jchip/require-at#readme

      +
      • (c) Joel Chen (https://github.com/jchip)
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1237,18 +1237,18 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and -limitations under the License. -
      -
      -
    42. -
    43. -
      - - domelementtype 2.3.0 - BSD-2-Clause - -

      https://github.com/fb55/domelementtype#readme

      -
      • Copyright (c) Felix Bohm
      -
      +limitations under the License.
      +        
      +
      +
    44. +
    45. +
      + + domelementtype 2.3.0 - BSD-2-Clause + +

      https://github.com/fb55/domelementtype#readme

      +
      • Copyright (c) Felix Bohm
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1260,18 +1260,18 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    46. -
    47. -
      - - domhandler 4.3.1 - BSD-2-Clause - -

      https://github.com/fb55/domhandler#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    48. +
    49. +
      + + domhandler 4.3.1 - BSD-2-Clause + +

      https://github.com/fb55/domhandler#readme

      +
      • Copyright (c) Felix Bohm
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1283,18 +1283,18 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    50. -
    51. -
      - - domutils 2.8.0 - BSD-2-Clause - -

      https://github.com/fb55/domutils#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    52. +
    53. +
      + + domutils 2.8.0 - BSD-2-Clause + +

      https://github.com/fb55/domutils#readme

      +
      • Copyright (c) Felix Bohm
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1306,18 +1306,18 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    54. -
    55. -
      - - dotenv 8.6.0 - BSD-2-Clause - -

      https://github.com/motdotla/dotenv#readme

      -
      • Copyright (c) 2015, Scott Motte
      -
      +
      +        
      +
      +
    56. +
    57. +
      + + dotenv 8.6.0 - BSD-2-Clause + +

      https://github.com/motdotla/dotenv#readme

      +
      • Copyright (c) 2015, Scott Motte
      +
               Copyright (c) 2015, Scott Motte
       All rights reserved.
       
      @@ -1341,18 +1341,18 @@ 

      NOTICES AND INFORMATION

      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    58. -
    59. -
      - - entities 2.2.0 - BSD-2-Clause - -

      https://github.com/fb55/entities#readme

      -
      • Copyright (c) Felix Bohm
      -
      +
      +        
      +
      +
    60. +
    61. +
      + + entities 2.2.0 - BSD-2-Clause + +

      https://github.com/fb55/entities#readme

      +
      • Copyright (c) Felix Bohm
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1364,18 +1364,18 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    62. -
    63. -
      - - webidl-conversions 3.0.1 - BSD-2-Clause - -

      https://github.com/jsdom/webidl-conversions#readme

      -
      • Copyright (c) 2014, Domenic Denicola
      -
      +
      +        
      +
      +
    64. +
    65. +
      + + webidl-conversions 3.0.1 - BSD-2-Clause + +

      https://github.com/jsdom/webidl-conversions#readme

      +
      • Copyright (c) 2014, Domenic Denicola
      +
               # The BSD 2-Clause License
       
       Copyright (c) 2014, Domenic Denicola
      @@ -1388,58 +1388,58 @@ 

      NOTICES AND INFORMATION

      2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    66. -
    67. -
      - - antlr4ts 0.4.1-alpha.0 - BSD-3-Clause - -

      https://github.com/tunnelvisionlabs/antlr4ts#readme

      + + +
      +
    68. +
    69. +
      + + antlr4ts 0.4.1-alpha.0 - BSD-3-Clause + +

      https://github.com/tunnelvisionlabs/antlr4ts#readme

      • Copyright 2016 The ANTLR Project.
      • -
      • Copyright (c) 2016 The ANTLR Project
      -
      -        [The "BSD license"]
      -Copyright (c) 2016 The ANTLR Project
      -All rights reserved.
      -
      -Redistribution and use in source and binary forms, with or without
      -modification, are permitted provided that the following conditions
      -are met:
      -
      - 1. Redistributions of source code must retain the above copyright
      -    notice, this list of conditions and the following disclaimer.
      - 2. Redistributions in binary form must reproduce the above copyright
      -    notice, this list of conditions and the following disclaimer in the
      -    documentation and/or other materials provided with the distribution.
      - 3. Neither the name of the copyright holder nor the names of its
      -    contributors may be used to endorse or promote products derived from
      -    this software without specific prior written permission.
      -
      -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      -
      -        
      -
      -
    70. -
    71. -
      - - moo 0.5.1 - BSD-3-Clause - -

      https://github.com/tjvr/moo#readme

      -
      • Copyright (c) 2017, Tim Radvan
      -
      +
    72. Copyright (c) 2016 The ANTLR Project
    73. +
      +        [The "BSD license"]
      +Copyright (c) 2016 The ANTLR Project
      +All rights reserved.
      +
      +Redistribution and use in source and binary forms, with or without
      +modification, are permitted provided that the following conditions
      +are met:
      +
      + 1. Redistributions of source code must retain the above copyright
      +    notice, this list of conditions and the following disclaimer.
      + 2. Redistributions in binary form must reproduce the above copyright
      +    notice, this list of conditions and the following disclaimer in the
      +    documentation and/or other materials provided with the distribution.
      + 3. Neither the name of the copyright holder nor the names of its
      +    contributors may be used to endorse or promote products derived from
      +    this software without specific prior written permission.
      +
      +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      +
      +        
      +
      +
    74. +
    75. +
      + + moo 0.5.1 - BSD-3-Clause + +

      https://github.com/tjvr/moo#readme

      +
      • Copyright (c) 2017, Tim Radvan
      +
               BSD 3-Clause License
       
       Copyright (c) 2017, Tim Radvan (tjvr)
      @@ -1469,18 +1469,18 @@ 

      NOTICES AND INFORMATION

      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
      -
      -
    76. -
    77. -
      - - railroad-diagrams 1.0.0 - CC0-1.0 - -

      https://github.com/tabatkins/railroad-diagrams

      - -
      +
      +        
      +
      +
    78. +
    79. +
      + + railroad-diagrams 1.0.0 - CC0-1.0 + +

      https://github.com/tabatkins/railroad-diagrams

      + +
               Creative Commons Legal Code
       
       CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
      @@ -1521,18 +1521,18 @@ 

      NOTICES AND INFORMATION

      c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. - d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. -
      -
      -
    80. -
    81. -
      - - graceful-fs 4.2.10 - ISC - -

      https://github.com/isaacs/node-graceful-fs#readme

      -
      • Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      -
      +      d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
      +        
      +
      +
    82. +
    83. +
      + + graceful-fs 4.2.10 - ISC + +

      https://github.com/isaacs/node-graceful-fs#readme

      +
      • Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      +
               The ISC License
       
       Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      @@ -1548,18 +1548,18 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    84. -
    85. -
      - - inherits 2.0.4 - ISC - -

      https://github.com/isaacs/inherits#readme

      -
      • Copyright (c) Isaac Z. Schlueter
      -
      +
      +        
      +
      +
    86. +
    87. +
      + + inherits 2.0.4 - ISC + +

      https://github.com/isaacs/inherits#readme

      +
      • Copyright (c) Isaac Z. Schlueter
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter
      @@ -1576,18 +1576,18 @@ 

      NOTICES AND INFORMATION

      OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    88. -
    89. -
      - - lru-cache 6.0.0 - ISC - -

      https://github.com/isaacs/node-lru-cache#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    90. +
    91. +
      + + lru-cache 6.0.0 - ISC + +

      https://github.com/isaacs/node-lru-cache#readme

      +
      • Copyright (c) Isaac Z. Schlueter and Contributors
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1603,18 +1603,18 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    92. -
    93. -
      - - pg-int8 1.0.1 - ISC - -

      https://github.com/charmander/pg-int8#readme

      -
      • Copyright (c) 2017, Charmander
      -
      +
      +        
      +
      +
    94. +
    95. +
      + + pg-int8 1.0.1 - ISC + +

      https://github.com/charmander/pg-int8#readme

      +
      • Copyright (c) 2017, Charmander
      +
               Copyright © 2017, Charmander <~@charmander.me>
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -1628,19 +1628,19 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    96. -
    97. -
      - - sax 1.2.4 - ISC - -

      https://github.com/isaacs/sax-js#readme

      + + +
      +
    98. +
    99. +
      + + sax 1.2.4 - ISC + +

      https://github.com/isaacs/sax-js#readme

      • Copyright (c) Isaac Z. Schlueter and Contributors
      • -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +
    100. Copyright Mathias Bynens <https://mathiasbynens.be/>
    101. +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1682,20 +1682,20 @@ 

      NOTICES AND INFORMATION

      LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    102. -
    103. -
      - - semver 6.3.0 - ISC - -

      https://github.com/npm/node-semver#readme

      + + +
      +
    104. +
    105. +
      + + semver 6.3.0 - ISC + +

      https://github.com/npm/node-semver#readme

      • Copyright Isaac Z.
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
    106. Copyright (c) Isaac Z. Schlueter and Contributors
    107. +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1711,19 +1711,19 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    108. -
    109. -
      - - semver 7.5.2 - ISC - -

      https://github.com/npm/node-semver#readme

      + + +
      +
    110. +
    111. +
      + + semver 7.5.2 - ISC + +

      https://github.com/npm/node-semver#readme

      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
    112. Copyright (c) Isaac Z. Schlueter and Contributors
    113. +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1739,18 +1739,18 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    114. -
    115. -
      - - universal-user-agent 6.0.0 - ISC - -

      https://github.com/gr2m/universal-user-agent#readme

      -
      • Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      -
      +
      +        
      +
      +
    116. +
    117. +
      + + universal-user-agent 6.0.0 - ISC + +

      https://github.com/gr2m/universal-user-agent#readme

      +
      • Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      +
               # [ISC License](https://spdx.org/licenses/ISC)
       
       Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      @@ -1758,18 +1758,18 @@ 

      NOTICES AND INFORMATION

      Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    118. -
    119. -
      - - yallist 4.0.0 - ISC - -

      https://github.com/isaacs/yallist#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +
      +        
      +
      +
    120. +
    121. +
      + + yallist 4.0.0 - ISC + +

      https://github.com/isaacs/yallist#readme

      +
      • Copyright (c) Isaac Z. Schlueter and Contributors
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1785,18 +1785,18 @@ 

      NOTICES AND INFORMATION

      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -
      -
      -
    122. -
    123. -
      - - @azure/abort-controller 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    124. +
    125. +
      + + @azure/abort-controller 1.0.2 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1818,18 +1818,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    126. -
    127. -
      - - @azure/arm-cosmosdb 15.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    128. +
    129. +
      + + @azure/arm-cosmosdb 15.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1850,18 +1850,18 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    130. -
    131. -
      - - @azure/arm-postgresql 6.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql

      -
      • Copyright (c) Microsoft Corporation.
      -
      +SOFTWARE.
      +        
      +
      +
    132. +
    133. +
      + + @azure/arm-postgresql 6.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1882,18 +1882,18 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    134. -
    135. -
      - - @azure/arm-postgresql-flexible 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible

      -
      • Copyright (c) Microsoft Corporation.
      -
      +SOFTWARE.
      +        
      +
      +
    136. +
    137. +
      + + @azure/arm-postgresql-flexible 5.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -1937,18 +1937,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    138. -
    139. -
      - - @azure/arm-resources 4.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    140. +
    141. +
      + + @azure/arm-resources 4.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1970,18 +1970,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    142. -
    143. -
      - - @azure/arm-resources 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    144. +
    145. +
      + + @azure/arm-resources 5.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -2002,18 +2002,18 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    146. -
    147. -
      - - @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid

      - -
      +SOFTWARE.
      +        
      +
      +
    148. +
    149. +
      + + @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid

      + +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2057,19 +2057,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    150. -
    151. -
      - - @azure/arm-resources-subscriptions 2.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions

      + + +
      +
    152. +
    153. +
      + + @azure/arm-resources-subscriptions 2.0.1 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions

      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    154. Copyright (c) Microsoft Corporation
    155. +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2090,19 +2090,19 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    156. -
    157. -
      - - @azure/arm-storage 18.2.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage

      +SOFTWARE. + +
      +
    158. +
    159. +
      + + @azure/arm-storage 18.2.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage

      • Copyright (c) 2023 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    160. Copyright (c) Microsoft Corporation
    161. +
               The MIT License (MIT)
       
       Copyright (c) 2023 Microsoft
      @@ -2123,20 +2123,20 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    162. -
    163. -
      - - @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid

      +SOFTWARE. + +
      +
    164. +
    165. +
      + + @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid

      • Copyright (c) 2020 Microsoft
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    166. Copyright (c) Microsoft Corporation
    167. +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2180,19 +2180,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    168. -
    169. -
      - - @azure/core-asynciterator-polyfill 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md

      + + +
      +
    170. +
    171. +
      + + @azure/core-asynciterator-polyfill 1.0.2 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md

      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    172. Copyright (c) Microsoft Corporation
    173. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2214,19 +2214,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    174. -
    175. -
      - - @azure/core-auth 1.5.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md

      + + +
      +
    176. +
    177. +
      + + @azure/core-auth 1.5.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md

      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    178. Copyright (c) Microsoft Corporation
    179. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2248,20 +2248,20 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    180. -
    181. -
      - - @azure/core-client 1.7.3 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/

      + + +
      +
    182. +
    183. +
      + + @azure/core-client 1.7.3 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/

      • Copyright (c) 2020 Microsoft
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const CollectionFormatToDelimiterMap CSV
      -
      +
    184. Copyright (c) Microsoft Corporation. const CollectionFormatToDelimiterMap CSV
    185. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2283,19 +2283,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    186. -
    187. -
      - - @azure/core-lro 2.5.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md

      + + +
      +
    188. +
    189. +
      + + @azure/core-lro 2.5.4 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md

      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    190. Copyright (c) Microsoft Corporation
    191. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2317,18 +2317,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    192. -
    193. -
      - - @azure/core-paging 1.2.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +
      +        
      +
      +
    194. +
    195. +
      + + @azure/core-paging 1.2.1 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md

      +
      • Copyright (c) Microsoft Corporation.
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2350,20 +2350,20 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    196. -
    197. -
      - - @azure/core-rest-pipeline 1.12.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/

      + + +
      +
    198. +
    199. +
      + + @azure/core-rest-pipeline 1.12.1 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/

      • Copyright (c) 2020 Microsoft
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const RedactedString REDACTED Make
      -
      +
    200. Copyright (c) Microsoft Corporation. const RedactedString REDACTED Make
    201. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2385,19 +2385,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    202. -
    203. -
      - - @azure/core-tracing 1.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md

      + + +
      +
    204. +
    205. +
      + + @azure/core-tracing 1.0.1 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md

      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    206. Copyright (c) Microsoft Corporation
    207. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2419,19 +2419,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    208. -
    209. -
      - - @azure/core-util 1.4.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/

      + + +
      +
    210. +
    211. +
      + + @azure/core-util 1.4.0 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/

      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    212. Copyright (c) Microsoft Corporation
    213. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2453,19 +2453,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    214. -
    215. -
      - - @azure/cosmos 3.15.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md

      + + +
      +
    216. +
    217. +
      + + @azure/cosmos 3.15.1 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md

      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) 2012-2015 Karan Lyons https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js
      -
      +
    218. Copyright (c) 2012-2015 Karan Lyons https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js
    219. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2487,19 +2487,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    220. -
    221. -
      - - @azure/logger 1.0.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md

      + + +
      +
    222. +
    223. +
      + + @azure/logger 1.0.4 - MIT + +

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md

      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +
    224. Copyright (c) Microsoft Corporation
    225. +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2521,19 +2521,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    226. -
    227. -
      - - @azure/ms-rest-azure-js 2.1.0 - MIT - -

      https://github.com/Azure/ms-rest-azure-js

      + + +
      +
    228. +
    229. +
      + + @azure/ms-rest-azure-js 2.1.0 - MIT + +

      https://github.com/Azure/ms-rest-azure-js

      • Copyright (c) 2017
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +
    230. Copyright (c) Microsoft Corporation.
    231. +
               MIT License
       
       Copyright (c) 2017 MIT
      @@ -2555,20 +2555,20 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    232. -
    233. -
      - - @azure/ms-rest-js 2.7.0 - MIT - -

      https://github.com/Azure/ms-rest-js

      + + +
      +
    234. +
    235. +
      + + @azure/ms-rest-js 2.7.0 - MIT + +

      https://github.com/Azure/ms-rest-js

      • copyright 2015 Toru Nagashima
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      -
      +
    236. Copyright (c) 2010-2016 Robert Kieffer and other contributors
    237. +
                   MIT License
       
           Copyright (c) Microsoft Corporation. All rights reserved.
      @@ -2590,53 +2590,53 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - -
      -
      -
    238. -
    239. -
      - - @microsoft/1ds-core-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      + + +
      +
    240. +
    241. +
      + + @microsoft/1ds-core-js 3.2.3 - MIT + +

      https://github.com/microsoft/ApplicationInsights-JS#readme

      • copyright Microsoft 2018
      • copyright Microsoft 2019
      • Copyright (c) Microsoft Corporation
      • copyright Microsoft 2019 Simplified
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018 import AppInsightsCore as InternalCore
      -
      -        Copyright (c) Microsoft Corporation.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -        
      -
      -
    242. -
    243. -
      - - @microsoft/1ds-post-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      +
    244. copyright Microsoft 2018 import AppInsightsCore as InternalCore
    245. +
      +        Copyright (c) Microsoft Corporation.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    246. +
    247. +
      + + @microsoft/1ds-post-js 3.2.3 - MIT + +

      https://github.com/microsoft/ApplicationInsights-JS#readme

      • copyright Microsoft 2018
      • copyright Microsoft 2020
      • copyright Microsoft 2018-2020
      • @@ -2644,106 +2644,106 @@

        NOTICES AND INFORMATION

      • Copyright (c) Microsoft Corporation
      • Copyright (c) Microsoft and contributors
      • copyright Microsoft 2018-2020 import IExtendedAppInsightsCore, SendRequestReason, EventSendType
      • -
      • copyright Microsoft 2018-2020 import IPerfManagerProvider, IValueSanitizer, FieldValueSanitizerType, FieldValueSanitizerFunc, SendRequestReason, EventSendType
      -
      -        Copyright (c) Microsoft Corporation.
      -
      -MIT License
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -        
      -
      -
    248. -
    249. -
      - - @microsoft/applicationinsights-core-js 2.8.4 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      +
    250. copyright Microsoft 2018-2020 import IPerfManagerProvider, IValueSanitizer, FieldValueSanitizerType, FieldValueSanitizerFunc, SendRequestReason, EventSendType
    251. +
      +        Copyright (c) Microsoft Corporation.
      +
      +MIT License
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    252. +
    253. +
      + + @microsoft/applicationinsights-core-js 2.8.4 - MIT + +

      https://github.com/microsoft/ApplicationInsights-JS#readme

      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation. All rights reserved.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    254. -
    255. -
      - - @microsoft/applicationinsights-shims 2.0.1 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims

      +
    256. Copyright (c) Microsoft and contributors
    257. +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation. All rights reserved.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    258. +
    259. +
      + + @microsoft/applicationinsights-shims 2.0.1 - MIT + +

      https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims

      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Microsoft and contributors.
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation. All rights reserved.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    260. -
    261. -
      - - @microsoft/dynamicproto-js 1.1.6 - MIT - -

      https://github.com/microsoft/DynamicProto-JS#readme

      +
    262. Copyright (c) Microsoft and contributors.
    263. +
      +            MIT License
      +
      +    Copyright (c) Microsoft Corporation. All rights reserved.
      +
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
      +
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
      +
      +        
      +
      +
    264. +
    265. +
      + + @microsoft/dynamicproto-js 1.1.6 - MIT + +

      https://github.com/microsoft/DynamicProto-JS#readme

      • (c) James Halliday
      • Copyright (c) Microsoft Corporation
      • Copyright (c) 2012 Maximilian Antoni
      • @@ -2760,97 +2760,44 @@

        NOTICES AND INFORMATION

      • Copyright 2013 jQuery Foundation, Inc. and other contributors
      • Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
      • Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright 2006 Google Inc. https://code.google.com/p/google-diff-match-patch
      -
      -            MIT License
      -
      -    Copyright (c) Microsoft Corporation.
      -
      -    Permission is hereby granted, free of charge, to any person obtaining a copy
      -    of this software and associated documentation files (the "Software"), to deal
      -    in the Software without restriction, including without limitation the rights
      -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -    copies of the Software, and to permit persons to whom the Software is
      -    furnished to do so, subject to the following conditions:
      -
      -    The above copyright notice and this permission notice shall be included in all
      -    copies or substantial portions of the Software.
      -
      -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -    SOFTWARE
      -
      -        
      -
      -
    266. -
    267. -
      - - @selderee/plugin-htmlparser2 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      -        MIT License
      -
      -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      -
      -Permission is hereby granted, free of charge, to any person obtaining a copy
      -of this software and associated documentation files (the "Software"), to deal
      -in the Software without restriction, including without limitation the rights
      -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      -copies of the Software, and to permit persons to whom the Software is
      -furnished to do so, subject to the following conditions:
      -
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      -
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      -SOFTWARE.
      -
      -        
      -
      -
    268. -
    269. -
      - - @tootallnate/once 1.1.2 - MIT - -

      https://github.com/TooTallNate/once#readme

      - -
      -        MIT License
      +
    270. Copyright 2006 Google Inc. https://code.google.com/p/google-diff-match-patch
    271. +
      +            MIT License
       
      -Copyright (c) <year> <copyright holders>
      +    Copyright (c) Microsoft Corporation.
       
      -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +    Permission is hereby granted, free of charge, to any person obtaining a copy
      +    of this software and associated documentation files (the "Software"), to deal
      +    in the Software without restriction, including without limitation the rights
      +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +    copies of the Software, and to permit persons to whom the Software is
      +    furnished to do so, subject to the following conditions:
       
      -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +    The above copyright notice and this permission notice shall be included in all
      +    copies or substantial portions of the Software.
      +
      +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +    SOFTWARE
       
      -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      -        
      -
      -
    272. -
    273. -
      - - @tootallnate/once 2.0.0 - MIT - -

      https://github.com/TooTallNate/once#readme

      -
      • Copyright (c) 2020 Nathan Rajlich
      -
      +        
      +
      +
    274. +
    275. +
      + + @selderee/plugin-htmlparser2 0.6.0 - MIT + +

      https://github.com/mxxii/selderee

      + +
               MIT License
       
      -Copyright (c) 2020 Nathan Rajlich
      +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
       of this software and associated documentation files (the "Software"), to deal
      @@ -2869,18 +2816,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    276. -
    277. -
      - - @typescript-plus/fast-memoize-decorator 0.1.0 - MIT - - - -
      +
      +        
      +
      +
    278. +
    279. +
      + + @tootallnate/once 1.1.2 - MIT + +

      https://github.com/TooTallNate/once#readme

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2889,24 +2836,21 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    280. -
    281. -
      - - @vscode/extension-telemetry 0.6.2 - MIT - -

      https://github.com/Microsoft/vscode-extension-telemetry#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      -        vscode-extension-telemetry
      -
      -The MIT License (MIT)
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    282. +
    283. +
      + + @tootallnate/once 2.0.0 - MIT + +

      https://github.com/TooTallNate/once#readme

      +
      • Copyright (c) 2020 Nathan Rajlich
      +
      +        MIT License
       
      -Copyright (c) Microsoft Corporation
      +Copyright (c) 2020 Nathan Rajlich
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
       of this software and associated documentation files (the "Software"), to deal
      @@ -2924,31 +2868,87 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
      -
      -
    284. -
    285. -
      - - 1to2 1.0.0 - MIT - - -
      • Copyright (c) 2014 3VOT
      -
      -        The MIT License (MIT)
      +SOFTWARE.
       
      -Copyright (c) 2014 3VOT
      +        
      +
      +
    286. +
    287. +
      + + @typescript-plus/fast-memoize-decorator 0.1.0 - MIT + + + +
      +        MIT License
       
      -Permission is hereby granted, free of charge, to any person obtaining a copy of
      -this software and associated documentation files (the "Software"), to deal in
      -the Software without restriction, including without limitation the rights to
      -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
      -the Software, and to permit persons to whom the Software is furnished to do so,
      -subject to the following conditions:
      +Copyright (c) <year> <copyright holders>
       
      -The above copyright notice and this permission notice shall be included in all
      -copies or substantial portions of the Software.
      +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    288. +
    289. +
      + + @vscode/extension-telemetry 0.6.2 - MIT + +

      https://github.com/Microsoft/vscode-extension-telemetry#readme

      +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      +
      +        vscode-extension-telemetry
      +
      +The MIT License (MIT)
      +
      +Copyright (c) Microsoft Corporation
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      +SOFTWARE.
      +        
      +
      +
    290. +
    291. +
      + + 1to2 1.0.0 - MIT + + +
      • Copyright (c) 2014 3VOT
      +
      +        The MIT License (MIT)
      +
      +Copyright (c) 2014 3VOT
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy of
      +this software and associated documentation files (the "Software"), to deal in
      +the Software without restriction, including without limitation the rights to
      +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
      +the Software, and to permit persons to whom the Software is furnished to do so,
      +subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in all
      +copies or substantial portions of the Software.
       
       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      @@ -2956,19 +2956,19 @@ 

      NOTICES AND INFORMATION

      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    292. -
    293. -
      - - abort-controller 3.0.0 - MIT - -

      https://github.com/mysticatea/abort-controller#readme

      + + +
      +
    294. +
    295. +
      + + abort-controller 3.0.0 - MIT + +

      https://github.com/mysticatea/abort-controller#readme

      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2017 Toru Nagashima
      -
      +
    296. Copyright (c) 2017 Toru Nagashima
    297. +
               MIT License
       
       Copyright (c) 2017 Toru Nagashima
      @@ -2990,18 +2990,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    298. -
    299. -
      - - agent-base 6.0.2 - MIT - -

      https://github.com/TooTallNate/node-agent-base#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +
      +        
      +
      +
    300. +
    301. +
      + + agent-base 6.0.2 - MIT + +

      https://github.com/TooTallNate/node-agent-base#readme

      +
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3010,18 +3010,18 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    302. -
    303. -
      - - async 3.2.3 - MIT - -

      https://caolan.github.io/async/

      -
      • Copyright (c) 2010-2018 Caolan McMahon
      -
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +        
      +
      +
    304. +
    305. +
      + + async 3.2.3 - MIT + +

      https://caolan.github.io/async/

      +
      • Copyright (c) 2010-2018 Caolan McMahon
      +
               Copyright (c) 2010-2018 Caolan McMahon
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3041,18 +3041,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    306. -
    307. -
      - - asynckit 0.4.0 - MIT - -

      https://github.com/alexindigo/asynckit#readme

      -
      • Copyright (c) 2016 Alex Indigo
      -
      +
      +        
      +
      +
    308. +
    309. +
      + + asynckit 0.4.0 - MIT + +

      https://github.com/alexindigo/asynckit#readme

      +
      • Copyright (c) 2016 Alex Indigo
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Alex Indigo
      @@ -3074,18 +3074,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    310. -
    311. -
      - - axios 0.21.4 - MIT - -

      https://axios-http.com/

      - -
      +
      +        
      +
      +
    312. +
    313. +
      + + axios 0.21.4 - MIT + +

      https://axios-http.com/

      + +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3105,18 +3105,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    314. -
    315. -
      - - axios 0.26.1 - MIT - -

      https://axios-http.com/

      -
      • Copyright (c) 2014-present Matt Zabriskie
      -
      +
      +        
      +
      +
    316. +
    317. +
      + + axios 0.26.1 - MIT + +

      https://axios-http.com/

      +
      • Copyright (c) 2014-present Matt Zabriskie
      +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3136,18 +3136,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    318. -
    319. -
      - - bl 2.2.1 - MIT - -

      https://github.com/rvagg/bl

      -
      • Copyright (c) 2013-2018 bl contributors
      -
      +
      +        
      +
      +
    320. +
    321. +
      + + bl 2.2.1 - MIT + +

      https://github.com/rvagg/bl

      +
      • Copyright (c) 2013-2018 bl contributors
      +
               The MIT License (MIT)
       =====================
       
      @@ -3161,18 +3161,18 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    322. -
    323. -
      - - buffer-writer 2.0.0 - MIT - -

      https://github.com/brianc/node-buffer-writer#readme

      - -
      +
      +        
      +
      +
    324. +
    325. +
      + + buffer-writer 2.0.0 - MIT + +

      https://github.com/brianc/node-buffer-writer#readme

      + +
               The MIT License (MIT)
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3192,18 +3192,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    326. -
    327. -
      - - combined-stream 1.0.8 - MIT - -

      https://github.com/felixge/node-combined-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +
      +        
      +
      +
    328. +
    329. +
      + + combined-stream 1.0.8 - MIT + +

      https://github.com/felixge/node-combined-stream

      +
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3223,18 +3223,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    330. -
    331. -
      - - commander 2.20.3 - MIT - -

      https://github.com/tj/commander.js#readme

      -
      • Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      -
      +
      +        
      +
      +
    332. +
    333. +
      + + commander 2.20.3 - MIT + +

      https://github.com/tj/commander.js#readme

      +
      • Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      +
               (The MIT License)
       
       Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3257,18 +3257,18 @@ 

      NOTICES AND INFORMATION

      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    334. -
    335. -
      - - core-util-is 1.0.2 - MIT - -

      https://github.com/isaacs/core-util-is#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +
      +        
      +
      +
    336. +
    337. +
      + + core-util-is 1.0.2 - MIT + +

      https://github.com/isaacs/core-util-is#readme

      +
      • Copyright Joyent, Inc. and other Node contributors
      +
               Copyright Node.js contributors. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3288,18 +3288,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    338. -
    339. -
      - - dayjs 1.11.2 - MIT - -

      https://day.js.org/

      -
      • Copyright (c) 2018-present, iamkun
      -
      +
      +        
      +
      +
    340. +
    341. +
      + + dayjs 1.11.2 - MIT + +

      https://day.js.org/

      +
      • Copyright (c) 2018-present, iamkun
      +
               MIT License
       
       Copyright (c) 2018-present, iamkun
      @@ -3321,19 +3321,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    342. -
    343. -
      - - debug 4.3.4 - MIT - -

      https://github.com/debug-js/debug#readme

      + + +
      +
    344. +
    345. +
      + + debug 4.3.4 - MIT + +

      https://github.com/debug-js/debug#readme

      • Copyright (c) 2018-2021 Josh Junon
      • -
      • Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      -
      +
    346. Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
    347. +
               (The MIT License)
       
       Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3354,18 +3354,18 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    348. -
    349. -
      - - deepmerge 4.2.2 - MIT - -

      https://github.com/TehShrike/deepmerge

      -
      • Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      -
      +
      +        
      +
      +
    350. +
    351. +
      + + deepmerge 4.2.2 - MIT + +

      https://github.com/TehShrike/deepmerge

      +
      • Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      @@ -3387,19 +3387,19 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    352. -
    353. -
      - - define-lazy-prop 2.0.0 - MIT - -

      https://github.com/sindresorhus/define-lazy-prop#readme

      + + +
      +
    354. +
    355. +
      + + define-lazy-prop 2.0.0 - MIT + +

      https://github.com/sindresorhus/define-lazy-prop#readme

      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +
    356. Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
    357. +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3409,18 +3409,18 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    358. -
    359. -
      - - delayed-stream 1.0.0 - MIT - -

      https://github.com/felixge/node-delayed-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +
      +        
      +
      +
    360. +
    361. +
      + + delayed-stream 1.0.0 - MIT + +

      https://github.com/felixge/node-delayed-stream

      +
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3440,18 +3440,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    362. -
    363. -
      - - discontinuous-range 1.0.0 - MIT - -

      https://github.com/dtudury/discontinuous-range

      -
      • Copyright (c) 2014 David Tudury
      -
      +
      +        
      +
      +
    364. +
    365. +
      + + discontinuous-range 1.0.0 - MIT + +

      https://github.com/dtudury/discontinuous-range

      +
      • Copyright (c) 2014 David Tudury
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 David Tudury
      @@ -3473,18 +3473,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    366. -
    367. -
      - - dom-serializer 1.4.1 - MIT - -

      https://github.com/cheeriojs/dom-renderer#readme

      -
      • Copyright (c) 2014 The cheeriojs contributors
      -
      +
      +        
      +
      +
    368. +
    369. +
      + + dom-serializer 1.4.1 - MIT + +

      https://github.com/cheeriojs/dom-renderer#readme

      +
      • Copyright (c) 2014 The cheeriojs contributors
      +
               License
       
       (The MIT License)
      @@ -3496,18 +3496,18 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    370. -
    371. -
      - - duplexer 0.1.1 - MIT - -

      https://github.com/Raynos/duplexer

      -
      • Copyright (c) 2012 Raynos.
      -
      +
      +        
      +
      +
    372. +
    373. +
      + + duplexer 0.1.1 - MIT + +

      https://github.com/Raynos/duplexer

      +
      • Copyright (c) 2012 Raynos.
      +
               Copyright (c) 2012 Raynos.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3526,19 +3526,19 @@ 

      NOTICES AND INFORMATION

      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -
      -
      -
    374. -
    375. -
      - - escape-string-regexp 2.0.0 - MIT - -

      https://github.com/sindresorhus/escape-string-regexp#readme

      +THE SOFTWARE. + +
      +
    376. +
    377. +
      + + escape-string-regexp 2.0.0 - MIT + +

      https://github.com/sindresorhus/escape-string-regexp#readme

      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +
    378. Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
    379. +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3548,18 +3548,18 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    380. -
    381. -
      - - event-stream 4.0.1 - MIT - -

      http://github.com/dominictarr/event-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +
      +        
      +
      +
    382. +
    383. +
      + + event-stream 4.0.1 - MIT + +

      http://github.com/dominictarr/event-stream

      +
      • Copyright (c) 2011 Dominic Tarr
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3584,19 +3584,19 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      -
    384. -
    385. -
      - - event-target-shim 5.0.1 - MIT - -

      https://github.com/mysticatea/event-target-shim

      + + +
      +
    386. +
    387. +
      + + event-target-shim 5.0.1 - MIT + +

      https://github.com/mysticatea/event-target-shim

      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2015 Toru Nagashima
      -
      +
    388. Copyright (c) 2015 Toru Nagashima
    389. +
               The MIT License (MIT)
       
       Copyright (c) 2015 Toru Nagashima
      @@ -3619,19 +3619,19 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
      -
      + + +
  14. -
  15. -
    - - fast-json-stable-stringify 2.1.0 - MIT - -

    https://github.com/epoberezkin/fast-json-stable-stringify

    +
  16. +
    + + fast-json-stable-stringify 2.1.0 - MIT + +

    https://github.com/epoberezkin/fast-json-stable-stringify

    • Copyright (c) 2013 James Halliday
    • -
    • Copyright (c) 2017 Evgeny Poberezkin
    -
    +
  17. Copyright (c) 2017 Evgeny Poberezkin
  18. +
             This software is released under the MIT license:
     
     Copyright (c) 2017 Evgeny Poberezkin
    @@ -3653,18 +3653,18 @@ 

    NOTICES AND INFORMATION

    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  19. -
  20. -
    - - fast-memoize 2.5.2 - MIT - -

    https://github.com/caiogondim/fast-memoize#readme

    -
    • Copyright (c) 2016 Caio Gondim
    -
    +
    +        
    +
    +
  21. +
  22. +
    + + fast-memoize 2.5.2 - MIT + +

    https://github.com/caiogondim/fast-memoize#readme

    +
    • Copyright (c) 2016 Caio Gondim
    +
             The MIT License (MIT)
     
     Copyright (c) 2016 Caio Gondim
    @@ -3686,18 +3686,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  23. -
  24. -
    - - follow-redirects 1.14.8 - MIT - -

    https://github.com/follow-redirects/follow-redirects

    -
    • Copyright 2014-present Olivier Lalonde <olalonde@gmail.com> , James Talmage <james@talmage.io> , Ruben Verborgh
    -
    +
    +        
    +
    +
  25. +
  26. +
    + + follow-redirects 1.14.8 - MIT + +

    https://github.com/follow-redirects/follow-redirects

    +
    • Copyright 2014-present Olivier Lalonde <olalonde@gmail.com> , James Talmage <james@talmage.io> , Ruben Verborgh
    +
             Copyright 2014–present Olivier Lalonde <olalonde@gmail.com>, James Talmage <james@talmage.io>, Ruben Verborgh
     
     Permission is hereby granted, free of charge, to any person obtaining a copy of
    @@ -3716,18 +3716,18 @@ 

    NOTICES AND INFORMATION

    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  27. -
  28. -
    - - form-data 2.5.1 - MIT - -

    https://github.com/form-data/form-data#readme

    -
    • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
    -
    +
    +        
    +
    +
  29. +
  30. +
    + + form-data 2.5.1 - MIT + +

    https://github.com/form-data/form-data#readme

    +
    • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
    +
             Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
     
      Permission is hereby granted, free of charge, to any person obtaining a copy
    @@ -3747,18 +3747,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  31. -
  32. -
    - - form-data 4.0.0 - MIT - -

    https://github.com/form-data/form-data#readme

    -
    • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
    -
    +
    +        
    +
    +
  33. +
  34. +
    + + form-data 4.0.0 - MIT + +

    https://github.com/form-data/form-data#readme

    +
    • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
    +
             Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
     
      Permission is hereby granted, free of charge, to any person obtaining a copy
    @@ -3778,18 +3778,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  35. -
  36. -
    - - from 0.1.7 - MIT - -

    https://github.com/dominictarr/from#readme

    -
    • Copyright (c) 2011 Dominic Tarr
    -
    +
    +        
    +
    +
  37. +
  38. +
    + + from 0.1.7 - MIT + +

    https://github.com/dominictarr/from#readme

    +
    • Copyright (c) 2011 Dominic Tarr
    +
             The MIT License
     
     Copyright (c) 2011 Dominic Tarr
    @@ -3814,20 +3814,20 @@ 

    NOTICES AND INFORMATION

    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  39. -
  40. -
    - - fs-extra 8.1.0 - MIT - -

    https://github.com/jprichardson/node-fs-extra

    + + +
    +
  41. +
  42. +
    + + fs-extra 8.1.0 - MIT + +

    https://github.com/jprichardson/node-fs-extra

    • Copyright (c) 2011-2017 JP Richardson
    • Copyright (c) 2011-2017 JP Richardson (https://github.com/jprichardson)
    • -
    • Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
    -
    +
  43. Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
  44. +
             (The MIT License)
     
     Copyright (c) 2011-2017 JP Richardson
    @@ -3843,18 +3843,18 @@ 

    NOTICES AND INFORMATION

    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  45. -
  46. -
    - - he 1.2.0 - MIT - -

    https://mths.be/he

    -
    • Copyright Mathias Bynens <https://mathiasbynens.be/>
    -
    +
    +        
    +
    +
  47. +
  48. +
    + + he 1.2.0 - MIT + +

    https://mths.be/he

    +
    • Copyright Mathias Bynens <https://mathiasbynens.be/>
    +
             Copyright Mathias Bynens <https://mathiasbynens.be/>
     
     Permission is hereby granted, free of charge, to any person obtaining
    @@ -3875,18 +3875,18 @@ 

    NOTICES AND INFORMATION

    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  49. -
  50. -
    - - htmlparser2 6.1.0 - MIT - -

    https://github.com/fb55/htmlparser2#readme

    -
    • Copyright 2010, 2011, Chris Winberry <chris@winberry.net>
    -
    +
    +        
    +
    +
  51. +
  52. +
    + + htmlparser2 6.1.0 - MIT + +

    https://github.com/fb55/htmlparser2#readme

    +
    • Copyright 2010, 2011, Chris Winberry <chris@winberry.net>
    +
             Copyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"), to
    @@ -3904,19 +3904,19 @@ 

    NOTICES AND INFORMATION

    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -
    -
    -
  53. -
  54. -
    - - html-to-text 8.2.0 - MIT - -

    https://github.com/html-to-text/node-html-to-text

    +IN THE SOFTWARE. + +
    +
  55. +
  56. +
    + + html-to-text 8.2.0 - MIT + +

    https://github.com/html-to-text/node-html-to-text

    • Portions Copyright (c) 2020 KillyMXI <killy@mxii.eu.org>
    • -
    • Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
    -
    +
  57. Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
  58. +
             MIT License
     
     Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
    @@ -3942,18 +3942,18 @@ 

    NOTICES AND INFORMATION

    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  59. -
  60. -
    - - http-proxy-agent 4.0.1 - MIT - -

    https://github.com/TooTallNate/node-http-proxy-agent#readme

    -
    • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
    -
    +
    +        
    +
    +
  61. +
  62. +
    + + http-proxy-agent 4.0.1 - MIT + +

    https://github.com/TooTallNate/node-http-proxy-agent#readme

    +
    • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -3962,18 +3962,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  63. -
  64. -
    - - http-proxy-agent 5.0.0 - MIT - -

    https://github.com/TooTallNate/node-http-proxy-agent#readme

    -
    • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  65. +
  66. +
    + + http-proxy-agent 5.0.0 - MIT + +

    https://github.com/TooTallNate/node-http-proxy-agent#readme

    +
    • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -3982,18 +3982,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  67. -
  68. -
    - - https-proxy-agent 5.0.0 - MIT - -

    https://github.com/TooTallNate/node-https-proxy-agent#readme

    -
    • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  69. +
  70. +
    + + https-proxy-agent 5.0.0 - MIT + +

    https://github.com/TooTallNate/node-https-proxy-agent#readme

    +
    • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -4002,18 +4002,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  71. -
  72. -
    - - indexable-array 0.7.0 - MIT - -

    https://github.com/ozum/indexable-array

    -
    • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net>
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  73. +
  74. +
    + + indexable-array 0.7.0 - MIT + +

    https://github.com/ozum/indexable-array

    +
    • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net>
    +
             The MIT License (MIT)
     
     Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net>
    @@ -4035,19 +4035,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  75. -
  76. -
    - - inflection 1.12.0 - MIT - -

    https://github.com/dreamerslab/node.inflection#readme

    + + +
    +
  77. +
  78. +
    + + inflection 1.12.0 - MIT + +

    https://github.com/dreamerslab/node.inflection#readme

    • Copyright (c) 2011
    • -
    • Copyright (c) 2011 Ben Lin <ben@dreamerslab.com>
    -
    +
  79. Copyright (c) 2011 Ben Lin <ben@dreamerslab.com>
  80. +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -4056,18 +4056,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  81. -
  82. -
    - - isarray 1.0.0 - MIT - -

    https://github.com/juliangruber/isarray

    -
    • Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  83. +
  84. +
    + + isarray 1.0.0 - MIT + +

    https://github.com/juliangruber/isarray

    +
    • Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -4076,18 +4076,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  85. -
  86. -
    - - is-docker 2.2.1 - MIT - -

    https://github.com/sindresorhus/is-docker#readme

    -
    • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  87. +
  88. +
    + + is-docker 2.2.1 - MIT + +

    https://github.com/sindresorhus/is-docker#readme

    +
    • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
    +
             MIT License
     
     Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
    @@ -4097,18 +4097,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  89. -
  90. -
    - - is-wsl 2.2.0 - MIT - -

    https://github.com/sindresorhus/is-wsl#readme

    -
    • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
    -
    +
    +        
    +
    +
  91. +
  92. +
    + + is-wsl 2.2.0 - MIT + +

    https://github.com/sindresorhus/is-wsl#readme

    +
    • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
    +
             MIT License
     
     Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
    @@ -4118,20 +4118,20 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  93. -
  94. -
    - - json5 2.2.3 - MIT - -

    http://json5.org/

    + + +
    +
  95. +
  96. +
    + + json5 2.2.3 - MIT + +

    http://json5.org/

    • (c) 2019 Denis Pushkarev
    • copyright (c) 2019 Denis Pushkarev
    • -
    • Copyright (c) 2012-2018 Aseem Kishore, and others
    -
    +
  97. Copyright (c) 2012-2018 Aseem Kishore, and others
  98. +
             MIT License
     
     Copyright (c) 2012-2018 Aseem Kishore, and [others].
    @@ -4155,54 +4155,54 @@ 

    NOTICES AND INFORMATION

    SOFTWARE. [others]: https://github.com/json5/json5/contributors - -
    -
    -
  99. -
  100. -
    - - jsonc-parser 2.2.1 - MIT - -

    https://github.com/microsoft/node-jsonc-parser#readme

    + + +
    +
  101. +
  102. +
    + + jsonc-parser 2.2.1 - MIT + +

    https://github.com/microsoft/node-jsonc-parser#readme

    • Copyright (c) Microsoft
    • Copyright 2018, Microsoft
    • -
    • Copyright (c) Microsoft Corporation.
    -
    -        The MIT License (MIT)
    -
    -Copyright (c) Microsoft
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy
    -of this software and associated documentation files (the "Software"), to deal
    -in the Software without restriction, including without limitation the rights
    -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -copies of the Software, and to permit persons to whom the Software is
    -furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all
    -copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -SOFTWARE.
    -
    -        
    -
    -
  103. -
  104. -
    - - jsonfile 4.0.0 - MIT - -

    https://github.com/jprichardson/node-jsonfile#readme

    +
  105. Copyright (c) Microsoft Corporation.
  106. +
    +        The MIT License (MIT)
    +
    +Copyright (c) Microsoft
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy
    +of this software and associated documentation files (the "Software"), to deal
    +in the Software without restriction, including without limitation the rights
    +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +copies of the Software, and to permit persons to whom the Software is
    +furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all
    +copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    +SOFTWARE.
    +
    +        
    +
    +
  107. +
  108. +
    + + jsonfile 4.0.0 - MIT + +

    https://github.com/jprichardson/node-jsonfile#readme

    • Copyright 2012-2016, JP Richardson <jprichardson@gmail.com>
    • -
    • Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
    -
    +
  109. Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
  110. +
             (The MIT License)
     
     Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
    @@ -4218,19 +4218,19 @@ 

    NOTICES AND INFORMATION

    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  111. -
  112. -
    - - jsonparse 1.3.1 - MIT - -

    https://github.com/creationix/jsonparse#readme

    + + +
    +
  113. +
  114. +
    + + jsonparse 1.3.1 - MIT + +

    https://github.com/creationix/jsonparse#readme

    • Copyright (c) 2012 Tim Caswell
    • -
    • Copyright (c) 2011-2012 Tim Caswell
    -
    +
  115. Copyright (c) 2011-2012 Tim Caswell
  116. +
             The MIT License
     
     Copyright (c) 2012 Tim Caswell
    @@ -4255,20 +4255,20 @@ 

    NOTICES AND INFORMATION

    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  117. -
  118. -
    - - lodash.get 4.4.2 - MIT - -

    https://lodash.com/

    + + +
    +
  119. +
  120. +
    + + lodash.get 4.4.2 - MIT + +

    https://lodash.com/

    • Copyright jQuery Foundation and other contributors <https://jquery.org/>
    • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
    • -
    • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
    -
    +
  121. copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
  122. +
             Copyright jQuery Foundation and other contributors <https://jquery.org/>
     
     Based on Underscore.js, copyright Jeremy Ashkenas,
    @@ -4316,20 +4316,20 @@ 

    NOTICES AND INFORMATION

    maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
    -
    -
  123. -
  124. -
    - - lodash.isfunction 3.0.9 - MIT - -

    https://lodash.com/

    + + +
    +
  125. +
  126. +
    + + lodash.isfunction 3.0.9 - MIT + +

    https://lodash.com/

    • Copyright JS Foundation and other contributors <https://js.foundation/>
    • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
    • -
    • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
    -
    +
  127. copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
  128. +
             Copyright JS Foundation and other contributors <https://js.foundation/>
     
     Based on Underscore.js, copyright Jeremy Ashkenas,
    @@ -4377,20 +4377,20 @@ 

    NOTICES AND INFORMATION

    maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
    -
    -
  129. -
  130. -
    - - lodash.set 4.3.2 - MIT - -

    https://lodash.com/

    + + +
    +
  131. +
  132. +
    + + lodash.set 4.3.2 - MIT + +

    https://lodash.com/

    • Copyright jQuery Foundation and other contributors <https://jquery.org/>
    • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
    • -
    • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
    -
    +
  133. copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
  134. +
             Copyright jQuery Foundation and other contributors <https://jquery.org/>
     
     Based on Underscore.js, copyright Jeremy Ashkenas,
    @@ -4438,20 +4438,20 @@ 

    NOTICES AND INFORMATION

    maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
    -
    -
  135. -
  136. -
    - - lodash.transform 4.6.0 - MIT - -

    https://lodash.com/

    + + +
    +
  137. +
  138. +
    + + lodash.transform 4.6.0 - MIT + +

    https://lodash.com/

    • Copyright jQuery Foundation and other contributors <https://jquery.org/>
    • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
    • -
    • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
    -
    +
  139. copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
  140. +
             Copyright jQuery Foundation and other contributors <https://jquery.org/>
     
     Based on Underscore.js, copyright Jeremy Ashkenas,
    @@ -4499,18 +4499,18 @@ 

    NOTICES AND INFORMATION

    maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms above. - -
    -
    -
  141. -
  142. -
    - - map-stream 0.0.7 - MIT - -

    http://github.com/dominictarr/map-stream

    -
    • Copyright (c) 2011 Dominic Tarr
    -
    +
    +        
    +
    +
  143. +
  144. +
    + + map-stream 0.0.7 - MIT + +

    http://github.com/dominictarr/map-stream

    +
    • Copyright (c) 2011 Dominic Tarr
    +
             The MIT License (MIT)
     
     Copyright (c) 2011 Dominic Tarr
    @@ -4535,18 +4535,18 @@ 

    NOTICES AND INFORMATION

    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  145. -
  146. -
    - - memory-pager 1.5.0 - MIT - -

    https://github.com/mafintosh/memory-pager

    -
    • Copyright (c) 2017 Mathias Buus
    -
    +
    +        
    +
    +
  147. +
  148. +
    + + memory-pager 1.5.0 - MIT + +

    https://github.com/mafintosh/memory-pager

    +
    • Copyright (c) 2017 Mathias Buus
    +
             The MIT License (MIT)
     
     Copyright (c) 2017 Mathias Buus
    @@ -4568,19 +4568,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  149. -
  150. -
    - - mime-db 1.44.0 - MIT - -

    https://github.com/jshttp/mime-db#readme

    + + +
    +
  151. +
  152. +
    + + mime-db 1.44.0 - MIT + +

    https://github.com/jshttp/mime-db#readme

    • Copyright (c) 2014 Jonathan Ong
    • -
    • Copyright (c) 2014 Jonathan Ong me@jongleberry.com
    -
    +
  153. Copyright (c) 2014 Jonathan Ong me@jongleberry.com
  154. +
             
     The MIT License (MIT)
     
    @@ -4603,21 +4603,21 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  155. -
  156. -
    - - mime-types 2.1.27 - MIT - -

    https://github.com/jshttp/mime-types#readme

    + + +
    +
  157. +
  158. +
    + + mime-types 2.1.27 - MIT + +

    https://github.com/jshttp/mime-types#readme

    • Copyright (c) 2014 Jonathan Ong
    • Copyright (c) 2015 Douglas Christopher Wilson
    • Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
    • -
    • Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
    -
    +
  159. Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
  160. +
             (The MIT License)
     
     Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
    @@ -4641,18 +4641,18 @@ 

    NOTICES AND INFORMATION

    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  161. -
  162. -
    - - minimist 1.2.6 - MIT - -

    https://github.com/substack/minimist

    - -
    +
    +        
    +
    +
  163. +
  164. +
    + + minimist 1.2.6 - MIT + +

    https://github.com/substack/minimist

    + +
             This software is released under the MIT license:
     
     Permission is hereby granted, free of charge, to any person obtaining a copy of
    @@ -4671,18 +4671,18 @@ 

    NOTICES AND INFORMATION

    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  165. -
  166. -
    - - moment 2.29.4 - MIT - -

    https://momentjs.com/

    -
    • Copyright (c) JS Foundation and other contributors
    -
    +
    +        
    +
    +
  167. +
  168. +
    + + moment 2.29.4 - MIT + +

    https://momentjs.com/

    +
    • Copyright (c) JS Foundation and other contributors
    +
             Copyright (c) JS Foundation and other contributors
     
     Permission is hereby granted, free of charge, to any person
    @@ -4705,18 +4705,18 @@ 

    NOTICES AND INFORMATION

    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  169. -
  170. -
    - - ms 2.1.2 - MIT - -

    https://github.com/zeit/ms#readme

    -
    • Copyright (c) 2016 Zeit, Inc.
    -
    +
    +        
    +
    +
  171. +
  172. +
    + + ms 2.1.2 - MIT + +

    https://github.com/zeit/ms#readme

    +
    • Copyright (c) 2016 Zeit, Inc.
    +
             The MIT License (MIT)
     
     Copyright (c) 2016 Zeit, Inc.
    @@ -4738,18 +4738,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  173. -
  174. -
    - - nearley 2.20.1 - MIT - -

    https://github.com/hardmath123/nearley#readme

    -
    • Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
    -
    +
    +        
    +
    +
  175. +
  176. +
    + + nearley 2.20.1 - MIT + +

    https://github.com/hardmath123/nearley#readme

    +
    • Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
    +
             The MIT License (MIT)
     
     Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
    @@ -4771,18 +4771,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  177. -
  178. -
    - - node-abort-controller 3.0.1 - MIT - -

    https://github.com/southpolesteve/node-abort-controller#readme

    - -
    +
    +        
    +
    +
  179. +
  180. +
    + + node-abort-controller 3.0.1 - MIT + +

    https://github.com/southpolesteve/node-abort-controller#readme

    + +
             MIT License
     
     Copyright (c) 2019 Steve Faulkner
    @@ -4804,18 +4804,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  181. -
  182. -
    - - node-fetch 2.6.7 - MIT - -

    https://github.com/bitinn/node-fetch

    -
    • Copyright (c) 2016 David Frank
    -
    +
    +        
    +
    +
  183. +
  184. +
    + + node-fetch 2.6.7 - MIT + +

    https://github.com/bitinn/node-fetch

    +
    • Copyright (c) 2016 David Frank
    +
             The MIT License (MIT)
     
     Copyright (c) 2016 David Frank
    @@ -4838,22 +4838,22 @@ 

    NOTICES AND INFORMATION

    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    + + +
  185. -
  186. -
    - - open 8.4.2 - MIT - -

    https://github.com/sindresorhus/open#readme

    +
  187. +
    + + open 8.4.2 - MIT + +

    https://github.com/sindresorhus/open#readme

    • Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
    • Copyright 2006, Jeremy White <jwhite@codeweavers.com>
    • Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
    • Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
    • -
    • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
    -
    +
  188. Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
  189. +
             MIT License
     
     Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
    @@ -4863,18 +4863,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  190. -
  191. -
    - - packet-reader 1.0.0 - MIT - -

    https://github.com/brianc/node-packet-reader

    -
    • Copyright 2015 Brian M. Carlson
    -
    +
    +        
    +
    +
  192. +
  193. +
    + + packet-reader 1.0.0 - MIT + +

    https://github.com/brianc/node-packet-reader

    +
    • Copyright 2015 Brian M. Carlson
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -4883,71 +4883,71 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  194. -
  195. -
    - - parseley 0.7.0 - MIT - -

    https://github.com/mxxii/parseley

    - -
    -        MIT License
    -
    -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy
    -of this software and associated documentation files (the "Software"), to deal
    -in the Software without restriction, including without limitation the rights
    -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -copies of the Software, and to permit persons to whom the Software is
    -furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all
    -copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -SOFTWARE.
    -
    -        
    -
    -
  196. -
  197. -
    - - performance-now 2.1.0 - MIT - -

    https://github.com/braveg1rl/performance-now

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  198. +
  199. +
    + + parseley 0.7.0 - MIT + +

    https://github.com/mxxii/parseley

    + +
    +        MIT License
    +
    +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy
    +of this software and associated documentation files (the "Software"), to deal
    +in the Software without restriction, including without limitation the rights
    +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +copies of the Software, and to permit persons to whom the Software is
    +furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all
    +copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    +SOFTWARE.
    +
    +        
    +
    +
  200. +
  201. +
    + + performance-now 2.1.0 - MIT + +

    https://github.com/braveg1rl/performance-now

    • Copyright (c) 2013 Braveg1rl
    • -
    • Copyright (c) 2017 Braveg1rl
    -
    +
  202. Copyright (c) 2017 Braveg1rl
  203. +
             Copyright (c) 2013 Braveg1rl
     
     Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
     
     The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
     
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -        
    -
    -
  204. -
  205. -
    - - pg 8.11.2 - MIT - -

    https://github.com/brianc/node-postgres

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  206. +
  207. +
    + + pg 8.11.2 - MIT + +

    https://github.com/brianc/node-postgres

    • Copyright (c) 2010 - 2021 Brian Carlson
    • -
    • Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
    -
    +
  208. Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
  209. +
             MIT License
     
     Copyright (c) 2010 - 2021 Brian Carlson
    @@ -4969,19 +4969,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  210. -
  211. -
    - - pg-cloudflare 1.1.1 - MIT - -

    https://github.com/brianc/node-postgres#readme

    + + +
    +
  212. +
  213. +
    + + pg-cloudflare 1.1.1 - MIT + +

    https://github.com/brianc/node-postgres#readme

    • Copyright (c) 2023 Brian M. Carlson
    • -
    • Copyright (c) 2010 - 2021 Brian Carlson
    -
    +
  214. Copyright (c) 2010 - 2021 Brian Carlson
  215. +
             MIT License
     
     Copyright (c) 2010 - 2021 Brian Carlson
    @@ -5003,19 +5003,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  216. -
  217. -
    - - pg-connection-string 2.6.2 - MIT - -

    https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string

    + + +
    +
  218. +
  219. +
    + + pg-connection-string 2.6.2 - MIT + +

    https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string

    • Copyright (c) 2014 Iced Development
    • -
    • Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
    -
    +
  220. Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
  221. +
             The MIT License (MIT)
     
     Copyright (c) 2014 Iced Development
    @@ -5036,18 +5036,18 @@ 

    NOTICES AND INFORMATION

    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -
    -
    -
  222. -
  223. -
    - - pgpass 1.0.2 - MIT - -

    https://github.com/hoegaarden/pgpass#readme

    -
    • Copyright (c) 2013-2016 Hannes Horl
    -
    +SOFTWARE.
    +        
    +
    +
  224. +
  225. +
    + + pgpass 1.0.2 - MIT + +

    https://github.com/hoegaarden/pgpass#readme

    +
    • Copyright (c) 2013-2016 Hannes Horl
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -5056,19 +5056,19 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  226. -
  227. -
    - - pg-pool 3.6.1 - MIT - -

    https://github.com/brianc/node-pg-pool#readme

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  228. +
  229. +
    + + pg-pool 3.6.1 - MIT + +

    https://github.com/brianc/node-pg-pool#readme

    • Copyright (c) 2016 Brian M. Carlson
    • -
    • Copyright (c) 2017 Brian M. Carlson
    -
    +
  230. Copyright (c) 2017 Brian M. Carlson
  231. +
             MIT License
     
     Copyright (c) 2017 Brian M. Carlson
    @@ -5090,18 +5090,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  232. -
  233. -
    - - pg-protocol 1.6.0 - MIT - -

    https://github.com/brianc/node-postgres#readme

    -
    • Copyright (c) 2010 - 2021 Brian Carlson
    -
    +
    +        
    +
    +
  234. +
  235. +
    + + pg-protocol 1.6.0 - MIT + +

    https://github.com/brianc/node-postgres#readme

    +
    • Copyright (c) 2010 - 2021 Brian Carlson
    +
             MIT License
     
     Copyright (c) 2010 - 2021 Brian Carlson
    @@ -5123,18 +5123,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  236. -
  237. -
    - - pg-structure 7.15.0 - MIT - -

    https://www.pg-structure.com/

    -
    • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net> (https://www.ozum.net/)
    -
    +
    +        
    +
    +
  238. +
  239. +
    + + pg-structure 7.15.0 - MIT + +

    https://www.pg-structure.com/

    +
    • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net> (https://www.ozum.net/)
    +
             The MIT License (MIT)
     
     Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net> (https://www.ozum.net/)
    @@ -5156,18 +5156,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  240. -
  241. -
    - - pg-types 2.2.0 - MIT - -

    https://github.com/brianc/node-pg-types

    -
    • Copyright (c) 2014 Brian M. Carlson
    -
    +
    +        
    +
    +
  242. +
  243. +
    + + pg-types 2.2.0 - MIT + +

    https://github.com/brianc/node-pg-types

    +
    • Copyright (c) 2014 Brian M. Carlson
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -5176,19 +5176,19 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  244. -
  245. -
    - - postgres-array 2.0.0 - MIT - -

    https://github.com/bendrucker/postgres-array#readme

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  246. +
  247. +
    + + postgres-array 2.0.0 - MIT + +

    https://github.com/bendrucker/postgres-array#readme

    • (c) Ben Drucker (http://bendrucker.me)
    • -
    • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
    -
    +
  248. Copyright (c) Ben Drucker <bvdrucker@gmail.com>
  249. +
             The MIT License (MIT)
     
     Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
    @@ -5210,19 +5210,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  250. -
  251. -
    - - postgres-bytea 1.0.0 - MIT - -

    https://github.com/bendrucker/postgres-bytea#readme

    + + +
    +
  252. +
  253. +
    + + postgres-bytea 1.0.0 - MIT + +

    https://github.com/bendrucker/postgres-bytea#readme

    • (c) Ben Drucker (http://bendrucker.me)
    • -
    • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
    -
    +
  254. Copyright (c) Ben Drucker <bvdrucker@gmail.com>
  255. +
             The MIT License (MIT)
     
     Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
    @@ -5244,19 +5244,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  256. -
  257. -
    - - postgres-date 1.0.6 - MIT - -

    https://github.com/bendrucker/postgres-date#readme

    + + +
    +
  258. +
  259. +
    + + postgres-date 1.0.6 - MIT + +

    https://github.com/bendrucker/postgres-date#readme

    • (c) Ben Drucker (http://bendrucker.me)
    • -
    • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
    -
    +
  260. Copyright (c) Ben Drucker <bvdrucker@gmail.com>
  261. +
             The MIT License (MIT)
     
     Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
    @@ -5278,19 +5278,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  262. -
  263. -
    - - postgres-interval 1.2.0 - MIT - -

    https://github.com/bendrucker/postgres-interval#readme

    + + +
    +
  264. +
  265. +
    + + postgres-interval 1.2.0 - MIT + +

    https://github.com/bendrucker/postgres-interval#readme

    • (c) Ben Drucker (http://bendrucker.me)
    • -
    • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
    -
    +
  266. Copyright (c) Ben Drucker <bvdrucker@gmail.com>
  267. +
             The MIT License (MIT)
     
     Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
    @@ -5312,18 +5312,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  268. -
  269. -
    - - priorityqueuejs 1.0.0 - MIT - -

    https://github.com/janogonzalez/priorityqueuejs

    - -
    +
    +        
    +
    +
  270. +
  271. +
    + + priorityqueuejs 1.0.0 - MIT + +

    https://github.com/janogonzalez/priorityqueuejs

    + +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -5332,18 +5332,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  272. -
  273. -
    - - process-nextick-args 2.0.1 - MIT - -

    https://github.com/calvinmetcalf/process-nextick-args

    -
    • Copyright (c) 2015 Calvin Metcalf
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  274. +
  275. +
    + + process-nextick-args 2.0.1 - MIT + +

    https://github.com/calvinmetcalf/process-nextick-args

    +
    • Copyright (c) 2015 Calvin Metcalf
    +
             # Copyright (c) 2015 Calvin Metcalf
     
     Permission is hereby granted, free of charge, to any person obtaining a copy
    @@ -5363,18 +5363,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** - -
    -
    -
  276. -
  277. -
    - - raf 3.4.1 - MIT - -

    https://github.com/chrisdickinson/raf#readme

    -
    • Copyright 2013 Chris Dickinson <chris@neversaw.us>
    -
    +
    +        
    +
    +
  278. +
  279. +
    + + raf 3.4.1 - MIT + +

    https://github.com/chrisdickinson/raf#readme

    +
    • Copyright 2013 Chris Dickinson <chris@neversaw.us>
    +
             Copyright 2013 Chris Dickinson <chris@neversaw.us>
     
     Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    @@ -5382,18 +5382,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  280. -
  281. -
    - - randexp 0.4.6 - MIT - -

    http://fent.github.io/randexp.js/

    -
    • Copyright (c) 2011 by Roly Fentanes
    -
    +
    +        
    +
    +
  282. +
  283. +
    + + randexp 0.4.6 - MIT + +

    http://fent.github.io/randexp.js/

    +
    • Copyright (c) 2011 by Roly Fentanes
    +
             Copyright (C) 2011 by Roly Fentanes
     
     Permission is hereby granted, free of charge, to any person obtaining a copy
    @@ -5413,18 +5413,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  284. -
  285. -
    - - readable-stream 2.3.7 - MIT - -

    https://github.com/nodejs/readable-stream#readme

    -
    • Copyright Joyent, Inc. and other Node contributors
    -
    +
    +        
    +
    +
  286. +
  287. +
    + + readable-stream 2.3.7 - MIT + +

    https://github.com/nodejs/readable-stream#readme

    +
    • Copyright Joyent, Inc. and other Node contributors
    +
             Node.js is licensed for use as follows:
     
     """
    @@ -5472,18 +5472,18 @@ 

    NOTICES AND INFORMATION

    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ - -
    -
    -
  288. -
  289. -
    - - ret 0.1.15 - MIT - -

    https://github.com/fent/ret.js#readme

    -
    • Copyright (c) 2011 by Roly Fentanes
    -
    +
    +        
    +
    +
  290. +
  291. +
    + + ret 0.1.15 - MIT + +

    https://github.com/fent/ret.js#readme

    +
    • Copyright (c) 2011 by Roly Fentanes
    +
             Copyright (C) 2011 by Roly Fentanes
     
     Permission is hereby granted, free of charge, to any person obtaining a copy
    @@ -5503,19 +5503,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  292. -
  293. -
    - - safe-buffer 5.1.2 - MIT - -

    https://github.com/feross/safe-buffer

    + + +
    +
  294. +
  295. +
    + + safe-buffer 5.1.2 - MIT + +

    https://github.com/feross/safe-buffer

    • Copyright (c) Feross Aboukhadijeh
    • -
    • Copyright (c) Feross Aboukhadijeh (http://feross.org)
    -
    +
  296. Copyright (c) Feross Aboukhadijeh (http://feross.org)
  297. +
             The MIT License (MIT)
     
     Copyright (c) Feross Aboukhadijeh
    @@ -5537,19 +5537,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  298. -
  299. -
    - - saslprep 1.0.3 - MIT - -

    https://github.com/reklatsmasters/saslprep#readme

    + + +
    +
  300. +
  301. +
    + + saslprep 1.0.3 - MIT + +

    https://github.com/reklatsmasters/saslprep#readme

    • (c) Dmitriy Tsvettsikh
    • -
    • Copyright (c) 2014 Dmitry Tsvettsikh
    -
    +
  302. Copyright (c) 2014 Dmitry Tsvettsikh
  303. +
             Copyright (c) 2014 Dmitry Tsvettsikh
     
     Permission is hereby granted, free of charge, to any person
    @@ -5571,51 +5571,51 @@ 

    NOTICES AND INFORMATION

    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  304. -
  305. -
    - - selderee 0.6.0 - MIT - -

    https://github.com/mxxii/selderee

    - -
    -        MIT License
    -
    -Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy
    -of this software and associated documentation files (the "Software"), to deal
    -in the Software without restriction, including without limitation the rights
    -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -copies of the Software, and to permit persons to whom the Software is
    -furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all
    -copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -SOFTWARE.
    -
    -        
    -
    -
  306. -
  307. -
    - - semaphore 1.0.5 - MIT - -

    https://github.com/abrkn/semaphore.js

    - -
    +OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  308. +
  309. +
    + + selderee 0.6.0 - MIT + +

    https://github.com/mxxii/selderee

    + +
    +        MIT License
    +
    +Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy
    +of this software and associated documentation files (the "Software"), to deal
    +in the Software without restriction, including without limitation the rights
    +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +copies of the Software, and to permit persons to whom the Software is
    +furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all
    +copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    +SOFTWARE.
    +
    +        
    +
    +
  310. +
  311. +
    + + semaphore 1.0.5 - MIT + +

    https://github.com/abrkn/semaphore.js

    + +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -5624,18 +5624,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  312. -
  313. -
    - - sorted-array-functions 1.3.0 - MIT - -

    https://github.com/mafintosh/sorted-array-functions

    -
    • Copyright (c) 2016 Mathias Buus
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  314. +
  315. +
    + + sorted-array-functions 1.3.0 - MIT + +

    https://github.com/mafintosh/sorted-array-functions

    +
    • Copyright (c) 2016 Mathias Buus
    +
             The MIT License (MIT)
     
     Copyright (c) 2016 Mathias Buus
    @@ -5657,18 +5657,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  316. -
  317. -
    - - sparse-bitfield 3.0.3 - MIT - -

    https://github.com/mafintosh/sparse-bitfield

    -
    • Copyright (c) 2016 Mathias Buus
    -
    +
    +        
    +
    +
  318. +
  319. +
    + + sparse-bitfield 3.0.3 - MIT + +

    https://github.com/mafintosh/sparse-bitfield

    +
    • Copyright (c) 2016 Mathias Buus
    +
             The MIT License (MIT)
     
     Copyright (c) 2016 Mathias Buus
    @@ -5690,18 +5690,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  320. -
  321. -
    - - split 1.0.1 - MIT - -

    http://github.com/dominictarr/split

    -
    • Copyright (c) 2011 Dominic Tarr
    -
    +
    +        
    +
    +
  322. +
  323. +
    + + split 1.0.1 - MIT + +

    http://github.com/dominictarr/split

    +
    • Copyright (c) 2011 Dominic Tarr
    +
             Copyright (c) 2011 Dominic Tarr
     
     Permission is hereby granted, free of charge, 
    @@ -5723,18 +5723,18 @@ 

    NOTICES AND INFORMATION

    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  324. -
  325. -
    - - stream-combiner 0.2.2 - MIT - -

    https://github.com/dominictarr/stream-combiner

    -
    • Copyright (c) 2012 Dominic Tarr
    -
    +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  326. +
  327. +
    + + stream-combiner 0.2.2 - MIT + +

    https://github.com/dominictarr/stream-combiner

    +
    • Copyright (c) 2012 Dominic Tarr
    +
             Copyright (c) 2012 'Dominic Tarr'
     
     Permission is hereby granted, free of charge, 
    @@ -5757,18 +5757,18 @@ 

    NOTICES AND INFORMATION

    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  328. -
  329. -
    - - string_decoder 1.1.1 - MIT - -

    https://github.com/nodejs/string_decoder

    -
    • Copyright Joyent, Inc. and other Node contributors
    -
    +
    +        
    +
    +
  330. +
  331. +
    + + string_decoder 1.1.1 - MIT + +

    https://github.com/nodejs/string_decoder

    +
    • Copyright Joyent, Inc. and other Node contributors
    +
             Node.js is licensed for use as follows:
     
     """
    @@ -5817,18 +5817,18 @@ 

    NOTICES AND INFORMATION

    IN THE SOFTWARE. """ - -
    -
    -
  332. -
  333. -
    - - tas-client 0.1.45 - MIT - - - -
    +
    +        
    +
    +
  334. +
  335. +
    + + tas-client 0.1.45 - MIT + + + +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -5837,18 +5837,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  336. -
  337. -
    - - through 2.3.8 - MIT - -

    https://github.com/dominictarr/through

    -
    • Copyright (c) 2011 Dominic Tarr
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  338. +
  339. +
    + + through 2.3.8 - MIT + +

    https://github.com/dominictarr/through

    +
    • Copyright (c) 2011 Dominic Tarr
    +
             The MIT License
     
     Copyright (c) 2011 Dominic Tarr
    @@ -5873,18 +5873,18 @@ 

    NOTICES AND INFORMATION

    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  340. -
  341. -
    - - tr46 0.0.3 - MIT - -

    https://github.com/Sebmaster/tr46.js#readme

    - -
    +
    +        
    +
    +
  342. +
  343. +
    + + tr46 0.0.3 - MIT + +

    https://github.com/Sebmaster/tr46.js#readme

    + +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -5893,18 +5893,18 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  344. -
  345. -
    - - tunnel 0.0.6 - MIT - -

    https://github.com/koichik/node-tunnel/

    -
    • Copyright (c) 2012 Koichi Kobayashi
    -
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +        
    +
    +
  346. +
  347. +
    + + tunnel 0.0.6 - MIT + +

    https://github.com/koichik/node-tunnel/

    +
    • Copyright (c) 2012 Koichi Kobayashi
    +
             The MIT License (MIT)
     
     Copyright (c) 2012 Koichi Kobayashi
    @@ -5926,19 +5926,19 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  348. -
  349. -
    - - underscore 1.12.1 - MIT - -

    https://underscorejs.org/

    + + +
    +
  350. +
  351. +
    + + underscore 1.12.1 - MIT + +

    https://underscorejs.org/

    • Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
    • -
    • (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore
    -
    +
  352. (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore
  353. +
             Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative
     Reporters & Editors
     
    @@ -5962,18 +5962,18 @@ 

    NOTICES AND INFORMATION

    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  354. -
  355. -
    - - universalify 0.1.2 - MIT - -

    https://github.com/RyanZim/universalify#readme

    -
    • Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
    -
    +
    +        
    +
    +
  356. +
  357. +
    + + universalify 0.1.2 - MIT + +

    https://github.com/RyanZim/universalify#readme

    +
    • Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
    +
             (The MIT License)
     
     Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
    @@ -5994,18 +5994,18 @@ 

    NOTICES AND INFORMATION

    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  358. -
  359. -
    - - util-deprecate 1.0.2 - MIT - -

    https://github.com/TooTallNate/util-deprecate

    -
    • Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
    -
    +
    +        
    +
    +
  360. +
  361. +
    + + util-deprecate 1.0.2 - MIT + +

    https://github.com/TooTallNate/util-deprecate

    +
    • Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
    +
             (The MIT License)
     
     Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
    @@ -6030,20 +6030,20 @@ 

    NOTICES AND INFORMATION

    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  362. -
  363. -
    - - uuid 3.4.0 - MIT - -

    https://github.com/uuidjs/uuid#readme

    + + +
    +
  364. +
  365. +
    + + uuid 3.4.0 - MIT + +

    https://github.com/uuidjs/uuid#readme

    • Copyright 2011, Sebastian Tschan https://blueimp.net
    • Copyright (c) 2010-2016 Robert Kieffer and other contributors
    • -
    • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
    -
    +
  366. Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
  367. +
             The MIT License (MIT)
     
     Copyright (c) 2010-2016 Robert Kieffer and other contributors
    @@ -6065,20 +6065,20 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  368. -
  369. -
    - - uuid 8.3.2 - MIT - -

    https://github.com/uuidjs/uuid#readme

    + + +
    +
  370. +
  371. +
    + + uuid 8.3.2 - MIT + +

    https://github.com/uuidjs/uuid#readme

    • Copyright 2011, Sebastian Tschan https://blueimp.net
    • Copyright (c) 2010-2020 Robert Kieffer and other contributors
    • -
    • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
    -
    +
  372. Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
  373. +
             The MIT License (MIT)
     
     Copyright (c) 2010-2020 Robert Kieffer and other contributors
    @@ -6088,20 +6088,20 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  374. -
  375. -
    - - uuid 9.0.1 - MIT - -

    https://github.com/uuidjs/uuid#readme

    + + +
    +
  376. +
  377. +
    + + uuid 9.0.1 - MIT + +

    https://github.com/uuidjs/uuid#readme

    • Copyright 2011, Sebastian Tschan https://blueimp.net
    • Copyright (c) 2010-2020 Robert Kieffer and other contributors
    • -
    • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
    -
    +
  378. Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
  379. +
             The MIT License (MIT)
     
     Copyright (c) 2010-2020 Robert Kieffer and other contributors
    @@ -6111,146 +6111,146 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  380. -
  381. -
    - - vscode-json-languageservice 3.5.2 - MIT - -

    https://github.com/Microsoft/vscode-json-languageservice#readme

    + + +
    +
  382. +
  383. +
    + + vscode-json-languageservice 3.5.2 - MIT + +

    https://github.com/Microsoft/vscode-json-languageservice#readme

    • Copyright (c) Microsoft
    • -
    • Copyright (c) Microsoft Corporation.
    -
    -        The MIT License (MIT)
    -
    -Copyright (c) Microsoft
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy
    -of this software and associated documentation files (the "Software"), to deal
    -in the Software without restriction, including without limitation the rights
    -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -copies of the Software, and to permit persons to whom the Software is
    -furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all
    -copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -SOFTWARE.
    -
    -        
    -
    -
  384. -
  385. -
    - - vscode-jsonrpc 5.0.1 - MIT - -

    https://github.com/Microsoft/vscode-languageserver-node#readme

    -
    • Copyright (c) Microsoft Corporation.
    -
    -        Copyright (c) Microsoft Corporation
    -
    -All rights reserved.
    -
    -MIT License
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -
    -        
    -
    -
  386. -
  387. -
    - - vscode-languageclient 6.1.3 - MIT - -

    https://github.com/Microsoft/vscode-languageserver-node#readme

    +
  388. Copyright (c) Microsoft Corporation.
  389. +
    +        The MIT License (MIT)
    +
    +Copyright (c) Microsoft
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy
    +of this software and associated documentation files (the "Software"), to deal
    +in the Software without restriction, including without limitation the rights
    +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +copies of the Software, and to permit persons to whom the Software is
    +furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all
    +copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    +SOFTWARE.
    +
    +        
    +
    +
  390. +
  391. +
    + + vscode-jsonrpc 5.0.1 - MIT + +

    https://github.com/Microsoft/vscode-languageserver-node#readme

    +
    • Copyright (c) Microsoft Corporation.
    +
    +        Copyright (c) Microsoft Corporation
    +
    +All rights reserved.
    +
    +MIT License
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +
    +        
    +
    +
  392. +
  393. +
    + + vscode-languageclient 6.1.3 - MIT + +

    https://github.com/Microsoft/vscode-languageserver-node#readme

    • Copyright (c) Microsoft Corporation.
    • -
    • Copyright (c) Isaac Z. Schlueter and Contributors
    -
    -        Copyright (c) Microsoft Corporation
    -
    -All rights reserved.
    -
    -MIT License
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -
    -        
    -
    -
  394. -
  395. -
    - - vscode-languageserver 6.1.1 - MIT - -

    https://github.com/Microsoft/vscode-languageserver-node#readme

    -
    • Copyright (c) Microsoft Corporation.
    -
    -        Copyright (c) Microsoft Corporation
    -
    -All rights reserved.
    -
    -MIT License
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -
    -        
    -
    -
  396. -
  397. -
    - - vscode-languageserver-protocol 3.15.3 - MIT - -

    https://github.com/Microsoft/vscode-languageserver-node#readme

    +
  398. Copyright (c) Isaac Z. Schlueter and Contributors
  399. +
    +        Copyright (c) Microsoft Corporation
    +
    +All rights reserved.
    +
    +MIT License
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +
    +        
    +
    +
  400. +
  401. +
    + + vscode-languageserver 6.1.1 - MIT + +

    https://github.com/Microsoft/vscode-languageserver-node#readme

    +
    • Copyright (c) Microsoft Corporation.
    +
    +        Copyright (c) Microsoft Corporation
    +
    +All rights reserved.
    +
    +MIT License
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +
    +        
    +
    +
  402. +
  403. +
    + + vscode-languageserver-protocol 3.15.3 - MIT + +

    https://github.com/Microsoft/vscode-languageserver-node#readme

    • Copyright (c) TypeFox and others.
    • -
    • Copyright (c) Microsoft Corporation.
    -
    -        Copyright (c) Microsoft Corporation
    -
    -All rights reserved.
    -
    -MIT License
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -
    -        
    -
    -
  404. -
  405. -
    - - vscode-languageserver-textdocument 1.0.1 - MIT - -

    https://github.com/Microsoft/vscode-languageserver-node#readme

    -
    • Copyright (c) Microsoft Corporation.
    -
    +
  406. Copyright (c) Microsoft Corporation.
  407. +
    +        Copyright (c) Microsoft Corporation
    +
    +All rights reserved.
    +
    +MIT License
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +
    +        
    +
    +
  408. +
  409. +
    + + vscode-languageserver-textdocument 1.0.1 - MIT + +

    https://github.com/Microsoft/vscode-languageserver-node#readme

    +
    • Copyright (c) Microsoft Corporation.
    +
             Copyright (c) Microsoft Corporation
     
     All rights reserved.
    @@ -6262,41 +6262,41 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  410. -
  411. -
    - - vscode-languageserver-types 3.15.1 - MIT - -

    https://github.com/Microsoft/vscode-languageserver-node#readme

    -
    • Copyright (c) Microsoft Corporation.
    -
    -        Copyright (c) Microsoft Corporation
    -
    -All rights reserved.
    -
    -MIT License
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -
    -        
    -
    -
  412. -
  413. -
    - - vscode-nls 4.1.2 - MIT - -

    https://github.com/Microsoft/vscode-nls#readme

    -
    • Copyright (c) Microsoft Corporation.
    -
    +
    +        
    +
    +
  414. +
  415. +
    + + vscode-languageserver-types 3.15.1 - MIT + +

    https://github.com/Microsoft/vscode-languageserver-node#readme

    +
    • Copyright (c) Microsoft Corporation.
    +
    +        Copyright (c) Microsoft Corporation
    +
    +All rights reserved.
    +
    +MIT License
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +
    +        
    +
    +
  416. +
  417. +
    + + vscode-nls 4.1.2 - MIT + +

    https://github.com/Microsoft/vscode-nls#readme

    +
    • Copyright (c) Microsoft Corporation.
    +
             The MIT License (MIT)
     
     Copyright (c) Microsoft Corporation
    @@ -6314,18 +6314,18 @@ 

    NOTICES AND INFORMATION

    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  418. -
  419. -
    - - vscode-tas-client 0.1.47 - MIT - - -
    • Copyright (c) Microsoft Corporation
    -
    +
    +        
    +
    +
  420. +
  421. +
    + + vscode-tas-client 0.1.47 - MIT + + +
    • Copyright (c) Microsoft Corporation
    +
             MIT License
     
     Copyright (c) <year> <copyright holders>
    @@ -6334,19 +6334,19 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  422. -
  423. -
    - - vscode-uri 1.0.8 - MIT - -

    https://github.com/Microsoft/vscode-uri#readme

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  424. +
  425. +
    + + vscode-uri 1.0.8 - MIT + +

    https://github.com/Microsoft/vscode-uri#readme

    • Copyright (c) Microsoft
    • -
    • Copyright (c) Microsoft Corporation.
    -
    +
  426. Copyright (c) Microsoft Corporation.
  427. +
             The MIT License (MIT)
     
     Copyright (c) Microsoft
    @@ -6355,19 +6355,19 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  428. -
  429. -
    - - vscode-uri 2.1.2 - MIT - -

    https://github.com/Microsoft/vscode-uri#readme

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  430. +
  431. +
    + + vscode-uri 2.1.2 - MIT + +

    https://github.com/Microsoft/vscode-uri#readme

    • Copyright (c) Microsoft
    • -
    • Copyright (c) Microsoft Corporation.
    -
    +
  432. Copyright (c) Microsoft Corporation.
  433. +
             The MIT License (MIT)
     
     Copyright (c) Microsoft
    @@ -6376,20 +6376,20 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  434. -
  435. -
    - - vscode-uri 3.0.7 - MIT - -

    https://github.com/microsoft/vscode-uri#readme

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  436. +
  437. +
    + + vscode-uri 3.0.7 - MIT + +

    https://github.com/microsoft/vscode-uri#readme

    • Copyright (c) Microsoft
    • Copyright (c) Microsoft Corporation
    • -
    • Copyright Joyent, Inc. and other Node contributors
    -
    +
  438. Copyright Joyent, Inc. and other Node contributors
  439. +
             The MIT License (MIT)
     
     Copyright (c) Microsoft
    @@ -6398,19 +6398,19 @@ 

    NOTICES AND INFORMATION

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    -
    -
  440. -
  441. -
    - - whatwg-url 5.0.0 - MIT - -

    https://github.com/jsdom/whatwg-url#readme

    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +
    +
  442. +
  443. +
    + + whatwg-url 5.0.0 - MIT + +

    https://github.com/jsdom/whatwg-url#readme

    • (c) extraPathPercentEncodeSet.has
    • -
    • Copyright (c) 2015-2016 Sebastian Mayr
    -
    +
  444. Copyright (c) 2015-2016 Sebastian Mayr
  445. +
             The MIT License (MIT)
     
     Copyright (c) 2015–2016 Sebastian Mayr
    @@ -6432,18 +6432,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  446. -
  447. -
    - - xml2js 0.5.0 - MIT - -

    https://github.com/Leonidas-from-XIV/node-xml2js

    -
    • Copyright 2010, 2011, 2012, 2013
    -
    +
    +        
    +
    +
  448. +
  449. +
    + + xml2js 0.5.0 - MIT + +

    https://github.com/Leonidas-from-XIV/node-xml2js

    +
    • Copyright 2010, 2011, 2012, 2013
    +
             Copyright 2010, 2011, 2012, 2013. All rights reserved.
     
     Permission is hereby granted, free of charge, to any person obtaining a copy
    @@ -6463,51 +6463,51 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  450. -
  451. -
    - - xmlbuilder 11.0.1 - MIT - -

    http://github.com/oozcitak/xmlbuilder-js

    -
    • Copyright (c) 2013 Ozgur Ozcitak
    -
    -        The MIT License (MIT)
    -
    -Copyright (c) 2013 Ozgur Ozcitak
    -
    -Permission is hereby granted, free of charge, to any person obtaining a copy
    -of this software and associated documentation files (the "Software"), to deal
    -in the Software without restriction, including without limitation the rights
    -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -copies of the Software, and to permit persons to whom the Software is
    -furnished to do so, subject to the following conditions:
    -
    -The above copyright notice and this permission notice shall be included in
    -all copies or substantial portions of the Software.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    -THE SOFTWARE.
    -
    -        
    -
    -
  452. -
  453. -
    - - xtend 4.0.2 - MIT - -

    https://github.com/Raynos/xtend

    -
    • Copyright (c) 2012-2014 Raynos
    -
    +
    +        
    +
    +
  454. +
  455. +
    + + xmlbuilder 11.0.1 - MIT + +

    http://github.com/oozcitak/xmlbuilder-js

    +
    • Copyright (c) 2013 Ozgur Ozcitak
    +
    +        The MIT License (MIT)
    +
    +Copyright (c) 2013 Ozgur Ozcitak
    +
    +Permission is hereby granted, free of charge, to any person obtaining a copy
    +of this software and associated documentation files (the "Software"), to deal
    +in the Software without restriction, including without limitation the rights
    +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +copies of the Software, and to permit persons to whom the Software is
    +furnished to do so, subject to the following conditions:
    +
    +The above copyright notice and this permission notice shall be included in
    +all copies or substantial portions of the Software.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    +THE SOFTWARE.
    +
    +        
    +
    +
  456. +
  457. +
    + + xtend 4.0.2 - MIT + +

    https://github.com/Raynos/xtend

    +
    • Copyright (c) 2012-2014 Raynos
    +
             The MIT License (MIT)
     Copyright (c) 2012-2014 Raynos.
     
    @@ -6528,18 +6528,18 @@ 

    NOTICES AND INFORMATION

    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  458. -
  459. -
    - - JSONStream 1.3.5 - MIT OR Apache-2.0 - -

    http://github.com/dominictarr/JSONStream

    -
    • Copyright (c) 2011 Dominic Tarr
    -
    +
    +        
    +
    +
  460. +
  461. +
    + + JSONStream 1.3.5 - MIT OR Apache-2.0 + +

    http://github.com/dominictarr/JSONStream

    +
    • Copyright (c) 2011 Dominic Tarr
    +
             The MIT License
     
     Copyright (c) 2011 Dominic Tarr
    @@ -6564,18 +6564,18 @@ 

    NOTICES AND INFORMATION

    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -
    -
    -
  462. -
  463. -
    - - pause-stream 0.0.11 - MIT OR Apache-2.0 - - -
    • Copyright (c) 2013 Dominic Tarr
    -
    +
    +        
    +
    +
  464. +
  465. +
    + + pause-stream 0.0.11 - MIT OR Apache-2.0 + + +
    • Copyright (c) 2013 Dominic Tarr
    +
             Dual Licensed MIT and Apache 2
     
     The MIT License
    @@ -6806,10 +6806,10 @@ 

    NOTICES AND INFORMATION

    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. -
    -
    -
  466. -
- - \ No newline at end of file + limitations under the License. + + + + + + diff --git a/README.md b/README.md index 4df65aec6..7e1e0a465 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,104 @@ - -# Azure Databases for VS Code (Preview) - - - -[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) - - - -Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). - -![Azure Databases Extension](resources/readme/overview.png) - -> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). - -# Prerequisites - -- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). - -# Features - -## Azure Databases Explorer - -- Create a database server by clicking the `+` button in the title -- View database servers and open directly in the portal -- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries -- Click on a document, stored procedure, or query to open in the editor -- Edit a document and persist changes to the cloud -- Attach a Mongo server by clicking the plug icon in the title - -![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) - -## Mongo Scrapbooks -### Run Mongo Commands with Rich Intellisense - -- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string -- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) -- Click on "New Mongo Scrapbook" in the tree title bar -- Click on "Connect to a database" to indicate which database to run the commands against -- Enter your commands and/or comments, eg: `db..find()` -- IntelliSense (auto-completions) will be provided -- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor -- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` -- Save and re-use later -![Mongo Scrapbook](resources/readme/Scrapbook.gif) - -## Import into Cosmos DB - -- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! -![Import documents](resources/readme/import_documents.gif) - -## Create an Azure Databases Server - -1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer - > If you don't already have an Azure Account, click "Create a Free Azure Account" -1. Select the 'plus' button to open the "Create Resource" menu - - ![Create resource](resources/readme/createResource.png) - -1. Choose "Create Database Server..." - - ![Create Database Server](resources/readme/createDatabaseServer.png) - -## Attach to the Cosmos DB Emulator - -* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine -* Right click 'Attached Database Accounts' and select 'Attach Emulator' - -![Attach Emulator](resources/readme/attachEmulator.png) - -## Known Issues - -- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. -- Graphs are not currently supported with the emulator -- Viewing/editing tables is not currently supported -- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). - - - -# Contributing -There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): - -* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. -* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! -* **Code**: Contribute bug fixes, features or design changes: - * Clone the repository locally and open in VS Code. - * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" - * Open the terminal (press CTRL+ \`) and run `npm install`. - * To build, press F1 and type in `Tasks: Run Build Task`. - * Debug: press F5 to start debugging the extension. - -## Legal -Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. - -## Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - - - -# Telemetry -VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). - -# License -[MIT](LICENSE.md) + +# Azure Databases for VS Code (Preview) + + + +[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) + + + +Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). + +![Azure Databases Extension](resources/readme/overview.png) + +> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). + +# Prerequisites + +- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). + +# Features + +## Azure Databases Explorer + +- Create a database server by clicking the `+` button in the title +- View database servers and open directly in the portal +- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries +- Click on a document, stored procedure, or query to open in the editor +- Edit a document and persist changes to the cloud +- Attach a Mongo server by clicking the plug icon in the title + +![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) + +## Mongo Scrapbooks +### Run Mongo Commands with Rich Intellisense + +- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string +- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) +- Click on "New Mongo Scrapbook" in the tree title bar +- Click on "Connect to a database" to indicate which database to run the commands against +- Enter your commands and/or comments, eg: `db..find()` +- IntelliSense (auto-completions) will be provided +- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor +- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` +- Save and re-use later +![Mongo Scrapbook](resources/readme/Scrapbook.gif) + +## Import into Cosmos DB + +- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! +![Import documents](resources/readme/import_documents.gif) + +## Create an Azure Databases Server + +1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer + > If you don't already have an Azure Account, click "Create a Free Azure Account" +1. Select the 'plus' button to open the "Create Resource" menu + + ![Create resource](resources/readme/createResource.png) + +1. Choose "Create Database Server..." + + ![Create Database Server](resources/readme/createDatabaseServer.png) + +## Attach to the Cosmos DB Emulator + +* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine +* Right click 'Attached Database Accounts' and select 'Attach Emulator' + +![Attach Emulator](resources/readme/attachEmulator.png) + +## Known Issues + +- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. +- Graphs are not currently supported with the emulator +- Viewing/editing tables is not currently supported +- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). + + + +# Contributing +There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): + +* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. +* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! +* **Code**: Contribute bug fixes, features or design changes: + * Clone the repository locally and open in VS Code. + * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" + * Open the terminal (press CTRL+ \`) and run `npm install`. + * To build, press F1 and type in `Tasks: Run Build Task`. + * Debug: press F5 to start debugging the extension. + +## Legal +Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. + +## Code of Conduct +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + + + +# Telemetry +VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). + +# License +[MIT](LICENSE.md) diff --git a/SECURITY.md b/SECURITY.md index f7b89984f..926b8ae40 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -38,4 +38,4 @@ We prefer all communications to be in English. Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - \ No newline at end of file + diff --git a/SUPPORT.md b/SUPPORT.md index 06703d2d0..bf4fade18 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,7 +2,8 @@ ## How to file issues and get help -This project uses GitHub Issues to track bugs and feature requests. Please see https://aka.ms/azCodeIssueReporting for our issue reporting guidelines. +This project uses GitHub Issues to track bugs and feature requests. Please see +https://aka.ms/azCodeIssueReporting for our issue reporting guidelines. ## Microsoft Support Policy diff --git a/Source/AzureDBExperiences.ts b/Source/AzureDBExperiences.ts index be9765dc6..97d2221cc 100644 --- a/Source/AzureDBExperiences.ts +++ b/Source/AzureDBExperiences.ts @@ -3,116 +3,202 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { nonNullProp } from './utils/nonNull'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; +import { nonNullProp } from "./utils/nonNull"; export enum API { - MongoDB = 'MongoDB', - Graph = 'Graph', - Table = 'Table', - Core = 'Core', - PostgresSingle = 'PostgresSingle', - PostgresFlexible = 'PostgresFlexible' + MongoDB = "MongoDB", + Graph = "Graph", + Table = "Table", + Core = "Core", + PostgresSingle = "PostgresSingle", + PostgresFlexible = "PostgresFlexible", } export enum DBAccountKind { - MongoDB = 'MongoDB', - GlobalDocumentDB = 'GlobalDocumentDB' + MongoDB = "MongoDB", + GlobalDocumentDB = "GlobalDocumentDB", } -export type CapabilityName = 'EnableGremlin' | 'EnableTable'; +export type CapabilityName = "EnableGremlin" | "EnableTable"; export function getExperienceFromApi(api: API): Experience { - let info = experiencesMap.get(api); - if (!info) { - info = { api: api, shortName: api, longName: api, kind: DBAccountKind.GlobalDocumentDB, tag: api }; - } - return info; + let info = experiencesMap.get(api); + if (!info) { + info = { + api: api, + shortName: api, + longName: api, + kind: DBAccountKind.GlobalDocumentDB, + tag: api, + }; + } + return info; } -export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string { - - const experience: Experience | undefined = tryGetExperience(databaseAccount); - if (experience) { - return experience.shortName; - } - // Must be some new kind of resource that we aren't aware of. Try to get a decent label - const defaultExperience: string = (databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience); - const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0]; - const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ''); - return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind'); - +export function getExperienceLabel( + databaseAccount: DatabaseAccountGetResults +): string { + const experience: Experience | undefined = + tryGetExperience(databaseAccount); + if (experience) { + return experience.shortName; + } + // Must be some new kind of resource that we aren't aware of. Try to get a decent label + const defaultExperience: string = ( + (databaseAccount && + databaseAccount.tags && + databaseAccount.tags.defaultExperience) + ); + const firstCapability = + databaseAccount.capabilities && databaseAccount.capabilities[0]; + const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, ""); + return ( + defaultExperience || + firstCapabilityName || + nonNullProp(databaseAccount, "kind") + ); } -export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined { - // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type - if (resource.kind === DBAccountKind.MongoDB) { - return MongoExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) { - return GremlinExperience; - } else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) { - return TableExperience; - } else if (resource.capabilities?.length === 0) { - return CoreExperience; - } - - return undefined; +export function tryGetExperience( + resource: DatabaseAccountGetResults +): Experience | undefined { + // defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type + if (resource.kind === DBAccountKind.MongoDB) { + return MongoExperience; + } else if ( + resource.capabilities?.find((cap) => cap.name === "EnableGremlin") + ) { + return GremlinExperience; + } else if ( + resource.capabilities?.find((cap) => cap.name === "EnableTable") + ) { + return TableExperience; + } else if (resource.capabilities?.length === 0) { + return CoreExperience; + } + + return undefined; } export interface Experience { - /** - * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) - */ - api: API; + /** + * Programmatic name used internally by us for historical reasons. Doesn't actually affect anything in Azure (maybe UI?) + */ + api: API; - longName: string; - shortName: string; - description?: string; + longName: string; + shortName: string; + description?: string; - // These properties are what the portal actually looks at to determine the difference between APIs - kind?: DBAccountKind; - capability?: CapabilityName; + // These properties are what the portal actually looks at to determine the difference between APIs + kind?: DBAccountKind; + capability?: CapabilityName; - // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) - tag?: string; + // The defaultExperience tag to place into the resource (has no actual effect in Azure, just imitating the portal) + tag?: string; } -export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return experiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } +export function getExperienceQuickPicks( + attached?: boolean +): IAzureQuickPickItem[] { + if (attached) { + return experiencesArray.map((exp) => + getExperienceQuickPickForAttached(exp.api) + ); + } else { + return experiencesArray.map((exp) => getExperienceQuickPick(exp.api)); + } } -export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem[] { - if (attached) { - return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api)); - } else { - return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api)); - } +export function getCosmosExperienceQuickPicks( + attached?: boolean +): IAzureQuickPickItem[] { + if (attached) { + return cosmosExperiencesArray.map((exp) => + getExperienceQuickPickForAttached(exp.api) + ); + } else { + return cosmosExperiencesArray.map((exp) => + getExperienceQuickPick(exp.api) + ); + } } -export function getExperienceQuickPick(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.longName, description: exp.description, data: exp }; +export function getExperienceQuickPick( + api: API +): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.longName, description: exp.description, data: exp }; } -export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem { - const exp = getExperienceFromApi(api); - return { label: exp.shortName, description: exp.description, data: exp }; +export function getExperienceQuickPickForAttached( + api: API +): IAzureQuickPickItem { + const exp = getExperienceFromApi(api); + return { label: exp.shortName, description: exp.description, data: exp }; } // Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB" // Table and Gremlin are distinguished from SQL by their capabilities -export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const; -export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const; -export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const; -export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const; -const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" }; -const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" }; - -const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience]; -const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience]; -const experiencesMap = new Map(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info])); +export const CoreExperience: Experience = { + api: API.Core, + longName: "Core", + description: "(SQL)", + shortName: "SQL", + kind: DBAccountKind.GlobalDocumentDB, + tag: "Core (SQL)", +} as const; +export const MongoExperience: Experience = { + api: API.MongoDB, + longName: "Azure Cosmos DB for MongoDB API", + shortName: "MongoDB", + kind: DBAccountKind.MongoDB, + tag: "Azure Cosmos DB for MongoDB API", +} as const; +export const TableExperience: Experience = { + api: API.Table, + longName: "Azure Table", + shortName: "Table", + kind: DBAccountKind.GlobalDocumentDB, + capability: "EnableTable", + tag: "Azure Table", +} as const; +export const GremlinExperience: Experience = { + api: API.Graph, + longName: "Gremlin", + description: "(graph)", + shortName: "Gremlin", + kind: DBAccountKind.GlobalDocumentDB, + capability: "EnableGremlin", + tag: "Gremlin (graph)", +} as const; +const PostgresSingleExperience: Experience = { + api: API.PostgresSingle, + longName: "PostgreSQL Single Server", + shortName: "PostgreSQLSingle", +}; +const PostgresFlexibleExperience: Experience = { + api: API.PostgresFlexible, + longName: "PostgreSQL Flexible Server", + shortName: "PostgreSQLFlexible", +}; + +const cosmosExperiencesArray: Experience[] = [ + CoreExperience, + MongoExperience, + TableExperience, + GremlinExperience, +]; +const experiencesArray: Experience[] = [ + ...cosmosExperiencesArray, + PostgresSingleExperience, + PostgresFlexibleExperience, +]; +const experiencesMap = new Map( + experiencesArray.map((info: Experience): [API, Experience] => [ + info.api, + info, + ]) +); diff --git a/Source/DatabasesFileSystem.ts b/Source/DatabasesFileSystem.ts index 93c2b4938..da2073ac0 100644 --- a/Source/DatabasesFileSystem.ts +++ b/Source/DatabasesFileSystem.ts @@ -3,7 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import { + AzExtTreeFileSystem, + AzExtTreeItem, + DialogResponses, + IActionContext, + UserCancelledError, +} from "@microsoft/vscode-azext-utils"; import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode"; import { FileChangeType } from "vscode-languageclient"; import { ext } from "./extensionVariables"; @@ -12,66 +18,103 @@ import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils"; import { getNodeEditorLabel } from "./utils/vscodeUtils"; export interface IEditableTreeItem extends AzExtTreeItem { - id: string; - filePath: string; - cTime: number; - mTime: number; - getFileContent(context: IActionContext): Promise; - writeFileContent(context: IActionContext, data: string): Promise; + id: string; + filePath: string; + cTime: number; + mTime: number; + getFileContent(context: IActionContext): Promise; + writeFileContent(context: IActionContext, data: string): Promise; } export class DatabasesFileSystem extends AzExtTreeFileSystem { - public static scheme: string = 'azureDatabases'; - public scheme: string = DatabasesFileSystem.scheme; - private _showSaveConfirmation: boolean = true; + public static scheme: string = "azureDatabases"; + public scheme: string = DatabasesFileSystem.scheme; + private _showSaveConfirmation: boolean = true; - public async statImpl(context: IActionContext, node: IEditableTreeItem): Promise { - const size: number = Buffer.byteLength(await node.getFileContent(context)); - return { type: FileType.File, ctime: node.cTime, mtime: node.mTime, size }; - } + public async statImpl( + context: IActionContext, + node: IEditableTreeItem + ): Promise { + const size: number = Buffer.byteLength( + await node.getFileContent(context) + ); + return { + type: FileType.File, + ctime: node.cTime, + mtime: node.mTime, + size, + }; + } - public async readFileImpl(context: IActionContext, node: IEditableTreeItem): Promise { - return Buffer.from(await node.getFileContent(context)); - } + public async readFileImpl( + context: IActionContext, + node: IEditableTreeItem + ): Promise { + return Buffer.from(await node.getFileContent(context)); + } - public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise { - const showSavePromptKey: string = 'showSavePrompt'; - // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" - const prefix: string = 'cosmosDB'; - const nodeEditorLabel: string = getNodeEditorLabel(node); - if (this._showSaveConfirmation && getWorkspaceSetting(showSavePromptKey, undefined, prefix)) { - const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel); - const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload); - if (result === DialogResponses.alwaysUpload) { - await updateGlobalSetting(showSavePromptKey, false, prefix); - } else if (result === DialogResponses.dontUpload) { - throw new UserCancelledError('dontUpload'); - } - } + public async writeFileImpl( + context: IActionContext, + node: IEditableTreeItem, + content: Uint8Array, + _originalUri: Uri + ): Promise { + const showSavePromptKey: string = "showSavePrompt"; + // NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases" + const prefix: string = "cosmosDB"; + const nodeEditorLabel: string = getNodeEditorLabel(node); + if ( + this._showSaveConfirmation && + getWorkspaceSetting(showSavePromptKey, undefined, prefix) + ) { + const message: string = localize( + "saveConfirmation", + 'Saving "{0}" will update the entity "{1}" to the cloud.', + node.filePath, + nodeEditorLabel + ); + const result: MessageItem | undefined = + await context.ui.showWarningMessage( + message, + { stepName: "writeFile" }, + DialogResponses.upload, + DialogResponses.alwaysUpload, + DialogResponses.dontUpload + ); + if (result === DialogResponses.alwaysUpload) { + await updateGlobalSetting(showSavePromptKey, false, prefix); + } else if (result === DialogResponses.dontUpload) { + throw new UserCancelledError("dontUpload"); + } + } - await node.writeFileContent(context, content.toString()); - await node.refresh(context); + await node.writeFileContent(context, content.toString()); + await node.refresh(context); - const updatedMessage: string = localize('updatedEntity', 'Updated entity "{0}".', nodeEditorLabel); - ext.outputChannel.appendLog(updatedMessage); - } + const updatedMessage: string = localize( + "updatedEntity", + 'Updated entity "{0}".', + nodeEditorLabel + ); + ext.outputChannel.appendLog(updatedMessage); + } - public getFilePath(node: IEditableTreeItem): string { - return node.filePath; - } + public getFilePath(node: IEditableTreeItem): string { + return node.filePath; + } - public async updateWithoutPrompt(uri: Uri): Promise { - const textDoc = await workspace.openTextDocument(uri); - this._showSaveConfirmation = false; - try { - await textDoc.save(); - } finally { - this._showSaveConfirmation = true; - } - } + public async updateWithoutPrompt(uri: Uri): Promise { + const textDoc = await workspace.openTextDocument(uri); + this._showSaveConfirmation = false; + try { + await textDoc.save(); + } finally { + this._showSaveConfirmation = true; + } + } - public fireChangedEvent(node: IEditableTreeItem): void { - node.mTime = Date.now(); - this.fireSoon({ type: FileChangeType.Changed, item: node }); - } + public fireChangedEvent(node: IEditableTreeItem): void { + node.mTime = Date.now(); + this.fireSoon({ type: FileChangeType.Changed, item: node }); + } } diff --git a/Source/ParsedConnectionString.ts b/Source/ParsedConnectionString.ts index 99654ef5a..1619d6390 100644 --- a/Source/ParsedConnectionString.ts +++ b/Source/ParsedConnectionString.ts @@ -4,25 +4,27 @@ *--------------------------------------------------------------------------------------------*/ export abstract class ParsedConnectionString { - public abstract readonly hostName: string; - public abstract readonly port: string; + public abstract readonly hostName: string; + public abstract readonly port: string; - /** - * databaseName may be undefined if this is an account-level connection string - */ - public readonly databaseName: string | undefined; - public readonly connectionString: string; + /** + * databaseName may be undefined if this is an account-level connection string + */ + public readonly databaseName: string | undefined; + public readonly connectionString: string; - constructor(connectionString: string, databaseName: string | undefined) { - this.connectionString = connectionString; - this.databaseName = databaseName; - } + constructor(connectionString: string, databaseName: string | undefined) { + this.connectionString = connectionString; + this.databaseName = databaseName; + } - public get accountId(): string { - return `${this.hostName}:${this.port}`; - } + public get accountId(): string { + return `${this.hostName}:${this.port}`; + } - public get fullId(): string { - return `${this.accountId}${this.databaseName ? '/' + this.databaseName : ''}`; - } + public get fullId(): string { + return `${this.accountId}${ + this.databaseName ? "/" + this.databaseName : "" + }`; + } } diff --git a/Source/azureAccountUtils.ts b/Source/azureAccountUtils.ts index 7f37da4cd..fbd474ae3 100644 --- a/Source/azureAccountUtils.ts +++ b/Source/azureAccountUtils.ts @@ -9,23 +9,32 @@ import { getApiExport } from "./getExtensionApi"; const azureAccountExtensionId = "ms-vscode.azure-account"; type AzureSession = { - userId: string; + userId: string; }; /** * @returns The user session of the signed-in azure account. */ -export async function getAzureAdUserSession(): Promise { - const azureAccountExport = await getApiExport(azureAccountExtensionId) as { sessions?: AzureSession[] }; - return azureAccountExport.sessions?.[0]; +export async function getAzureAdUserSession(): Promise< + AzureSession | undefined +> { + const azureAccountExport = (await getApiExport( + azureAccountExtensionId + )) as { sessions?: AzureSession[] }; + return azureAccountExport.sessions?.[0]; } /** * Gets a function that can request an access token for a specified scope for the signed-in azure account. */ -export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise { - return async () => { - const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined; - return getTokenResult?.token ?? ""; - }; +export function getTokenFunction( + credentials: AzExtServiceClientCredentials, + scope: string +): () => Promise { + return async () => { + const getTokenResult = (await credentials.getToken(scope)) as + | { token: string } + | undefined; + return getTokenResult?.token ?? ""; + }; } diff --git a/Source/constants.ts b/Source/constants.ts index 0e6a4a14e..4d43ec018 100644 --- a/Source/constants.ts +++ b/Source/constants.ts @@ -5,47 +5,62 @@ export const isWindows: boolean = /^win/.test(process.platform); -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import { CoreExperience, GremlinExperience, MongoExperience, TableExperience } from './AzureDBExperiences'; -import { ext } from './extensionVariables'; +import * as assert from "assert"; +import * as fs from "fs"; +import * as path from "path"; +import { + CoreExperience, + GremlinExperience, + MongoExperience, + TableExperience, +} from "./AzureDBExperiences"; +import { ext } from "./extensionVariables"; export namespace Links { - export const LocalConnectionDebuggingTips: string = 'https://aka.ms/AA5zah5'; + export const LocalConnectionDebuggingTips: string = + "https://aka.ms/AA5zah5"; } export interface IThemedIconPath { - light: string; - dark: string; + light: string; + dark: string; } export function getThemedIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'light', iconName), - dark: path.join(getResourcesPath(), 'icons', 'dark', iconName) - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join(getResourcesPath(), "icons", "light", iconName), + dark: path.join(getResourcesPath(), "icons", "dark", iconName), + }; + assert(fs.existsSync(a.light)); + return a; } export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath { - const a = { - light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName), - dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName) - }; - assert(fs.existsSync(a.light)); - return a; + const a = { + light: path.join( + getResourcesPath(), + "icons", + "theme-agnostic", + iconName + ), + dark: path.join( + getResourcesPath(), + "icons", + "theme-agnostic", + iconName + ), + }; + assert(fs.existsSync(a.light)); + return a; } export function getResourcesPath(): string { - return ext.context.asAbsolutePath('resources'); + return ext.context.asAbsolutePath("resources"); } export const doubleClickDebounceDelay = 500; //milliseconds -export const defaultStoredProcedure = - `function sample(prefix) { +export const defaultStoredProcedure = `function sample(prefix) { var collection = getContext().getCollection(); // Query documents and take 1st item. @@ -70,67 +85,69 @@ export const defaultStoredProcedure = }); if (!isAccepted) throw new Error('The query was not accepted by the server.'); -};` ; +};`; -export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='; +export const emulatorPassword = + "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; // https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell -export const testDb: string = 'test'; +export const testDb: string = "test"; -export const connectedPostgresKey: string = 'ms-azuretools.vscode-azuredatabases.connectedPostgresDB'; -export const postgresLanguageId: string = 'postgres'; +export const connectedPostgresKey: string = + "ms-azuretools.vscode-azuredatabases.connectedPostgresDB"; +export const postgresLanguageId: string = "postgres"; export const postgresFileExtension: string = `.psql`; -export const postgresBaseFileName: string = 'query'; -export const postgresDefaultPort = '5432'; -export const postgresDefaultDatabase = 'postgres'; -export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless'; +export const postgresBaseFileName: string = "query"; +export const postgresDefaultPort = "5432"; +export const postgresDefaultDatabase = "postgres"; +export const SERVERLESS_CAPABILITY_NAME = "EnableServerless"; -export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts'; +export const databaseAccountType = "Microsoft.DocumentDB/databaseAccounts"; export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API"; export const cosmosMongoFilter = { - type: databaseAccountType, - kind: MongoExperience.kind, - tags: { - defaultExperience: mongoDefaultExperienceTag - } + type: databaseAccountType, + kind: MongoExperience.kind, + tags: { + defaultExperience: mongoDefaultExperienceTag, + }, }; -export const gremlinDefaultExperienceTag = 'Gremlin (graph)'; +export const gremlinDefaultExperienceTag = "Gremlin (graph)"; export const cosmosGremlinFilter = { - type: databaseAccountType, - kind: GremlinExperience.kind, - tags: { - defaultExperience: gremlinDefaultExperienceTag - } + type: databaseAccountType, + kind: GremlinExperience.kind, + tags: { + defaultExperience: gremlinDefaultExperienceTag, + }, }; -export const tableDefaultExperienceTag = 'Azure Table'; +export const tableDefaultExperienceTag = "Azure Table"; export const cosmosTableFilter = { - type: databaseAccountType, - kind: TableExperience.kind, - tags: { - defaultExperience: tableDefaultExperienceTag - } + type: databaseAccountType, + kind: TableExperience.kind, + tags: { + defaultExperience: tableDefaultExperienceTag, + }, }; -export const sqlDefaultExperienceTag = 'Core (SQL)'; +export const sqlDefaultExperienceTag = "Core (SQL)"; export const sqlFilter = { - type: databaseAccountType, - kind: CoreExperience.kind, - tags: { - defaultExperience: sqlDefaultExperienceTag - } + type: databaseAccountType, + kind: CoreExperience.kind, + tags: { + defaultExperience: sqlDefaultExperienceTag, + }, }; export const postgresFlexibleFilter = { - type: 'Microsoft.DBforPostgreSQL/flexibleServers' + type: "Microsoft.DBforPostgreSQL/flexibleServers", }; export const postgresSingleFilter = { - type: 'Microsoft.DBForPostgreSQL/servers' + type: "Microsoft.DBForPostgreSQL/servers", }; diff --git a/Source/extension.ts b/Source/extension.ts index e68744157..c712fbc4c 100644 --- a/Source/extension.ts +++ b/Source/extension.ts @@ -3,213 +3,409 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils'; -import { AzExtResourceType } from '@microsoft/vscode-azureresources-api'; -import { platform } from 'os'; -import * as vscode from 'vscode'; -import { DatabasesFileSystem } from './DatabasesFileSystem'; -import { findTreeItem } from './commands/api/findTreeItem'; -import { pickTreeItem } from './commands/api/pickTreeItem'; -import { revealTreeItem } from './commands/api/revealTreeItem'; -import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { importDocuments } from './commands/importDocuments'; -import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants'; -import { registerDocDBCommands } from './docdb/registerDocDBCommands'; -import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem'; -import { ext } from './extensionVariables'; -import { getResourceGroupsApi } from './getExtensionApi'; -import { registerGraphCommands } from './graph/registerGraphCommands'; -import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem'; -import { registerMongoCommands } from './mongo/registerMongoCommands'; -import { setConnectedNode } from './mongo/setConnectedNode'; -import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem'; -import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem'; -import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands'; -import { DatabaseResolver } from './resolver/AppResolver'; -import { DatabaseWorkspaceProvider } from './resolver/DatabaseWorkspaceProvider'; -import { TableAccountTreeItem } from './table/tree/TableAccountTreeItem'; -import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem'; -import { localize } from './utils/localize'; - -const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue]; - -export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise { - ext.context = context; - ext.ignoreBundle = ignoreBundle; - - ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); - context.subscriptions.push(ext.outputChannel); - registerUIExtensionVariables(ext); - registerAzureUtilsExtensionVariables(ext); - - await callWithTelemetryAndErrorHandling('cosmosDB.activate', async (activateContext: IActionContext) => { - activateContext.telemetry.properties.isActivationEvent = 'true'; - activateContext.telemetry.measurements.mainFileLoad = (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; - - ext.secretStorage = context.secrets; - - ext.rgApi = await getResourceGroupsApi(); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver()); - ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver()); - - const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem; - const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem); - ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider); - - ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); - - registerDocDBCommands(); - registerGraphCommands(); - registerPostgresCommands(); - registerMongoCommands(); - - context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem)); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions")); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => { - await ext.attachedAccountsNode.attachNewAccount(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => { - if (platform() !== 'win32') { - actionContext.errorHandling.suppressReportIssue = true; - throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.')); - } - - await ext.attachedAccountsNode.attachEmulator(actionContext); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - }); - registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => { - if (node) { - await node.refresh(actionContext); - } else { - await ext.rgApi.appResourceTree.refresh(actionContext, node); - } - }); - - registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => { - const children = await ext.attachedAccountsNode.loadAllChildren(actionContext); - if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") { - const message = localize('noAttachedAccounts', 'There are no Attached Accounts.'); - void vscode.window.showInformationMessage(message); - } else { - if (!node) { - node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext); - } - if (node instanceof MongoAccountTreeItem) { - if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) { - setConnectedNode(undefined); - await node.refresh(actionContext); - } - } - await ext.attachedAccountsNode.detach(node); - await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => { - if (selectedNode instanceof vscode.Uri) { - await importDocuments(actionContext, uris || [selectedNode], undefined); - } else { - await importDocuments(actionContext, undefined, selectedNode); - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => { - if (!node) { - node = await ext.rgApi.pickAppResource(actionContext, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue] - }); - } - - // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 - ext.fileSystem.fireChangedEvent(node); - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri)); - registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext)); - registerEvent( - 'cosmosDB.onDidChangeConfiguration', - vscode.workspace.onDidChangeConfiguration, - async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => { - actionContext.telemetry.properties.isActivationEvent = "true"; - actionContext.errorHandling.suppressDisplay = true; - if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) { - await vscode.commands.executeCommand("azureDatabases.refresh"); - } - }); - - // Suppress "Report an Issue" button for all errors in favor of the command - registerErrorHandler(c => c.errorHandling.suppressReportIssue = true); - registerReportIssueCommand('azureDatabases.reportIssue'); - }); - - return createApiProvider([{ - findTreeItem, - pickTreeItem, - revealTreeItem, - apiVersion: '1.2.0' - }]); +"use strict"; + +import { registerAzureUtilsExtensionVariables } from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + AzureExtensionApi, + IActionContext, + ITreeItemPickerContext, + apiUtils, + callWithTelemetryAndErrorHandling, + createApiProvider, + createAzExtOutputChannel, + registerCommandWithTreeNodeUnwrapping, + registerErrorHandler, + registerEvent, + registerReportIssueCommand, + registerUIExtensionVariables, +} from "@microsoft/vscode-azext-utils"; +import { AzExtResourceType } from "@microsoft/vscode-azureresources-api"; +import { platform } from "os"; +import * as vscode from "vscode"; +import { DatabasesFileSystem } from "./DatabasesFileSystem"; +import { findTreeItem } from "./commands/api/findTreeItem"; +import { pickTreeItem } from "./commands/api/pickTreeItem"; +import { revealTreeItem } from "./commands/api/revealTreeItem"; +import { deleteDatabaseAccount } from "./commands/deleteDatabaseAccount/deleteDatabaseAccount"; +import { importDocuments } from "./commands/importDocuments"; +import { + cosmosGremlinFilter, + cosmosMongoFilter, + cosmosTableFilter, + doubleClickDebounceDelay, + sqlFilter, +} from "./constants"; +import { registerDocDBCommands } from "./docdb/registerDocDBCommands"; +import { DocDBAccountTreeItem } from "./docdb/tree/DocDBAccountTreeItem"; +import { DocDBAccountTreeItemBase } from "./docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBCollectionTreeItem } from "./docdb/tree/DocDBCollectionTreeItem"; +import { DocDBDocumentTreeItem } from "./docdb/tree/DocDBDocumentTreeItem"; +import { ext } from "./extensionVariables"; +import { getResourceGroupsApi } from "./getExtensionApi"; +import { registerGraphCommands } from "./graph/registerGraphCommands"; +import { GraphAccountTreeItem } from "./graph/tree/GraphAccountTreeItem"; +import { registerMongoCommands } from "./mongo/registerMongoCommands"; +import { setConnectedNode } from "./mongo/setConnectedNode"; +import { MongoAccountTreeItem } from "./mongo/tree/MongoAccountTreeItem"; +import { MongoCollectionTreeItem } from "./mongo/tree/MongoCollectionTreeItem"; +import { MongoDocumentTreeItem } from "./mongo/tree/MongoDocumentTreeItem"; +import { registerPostgresCommands } from "./postgres/commands/registerPostgresCommands"; +import { DatabaseResolver } from "./resolver/AppResolver"; +import { DatabaseWorkspaceProvider } from "./resolver/DatabaseWorkspaceProvider"; +import { TableAccountTreeItem } from "./table/tree/TableAccountTreeItem"; +import { AttachedAccountSuffix } from "./tree/AttachedAccountsTreeItem"; +import { SubscriptionTreeItem } from "./tree/SubscriptionTreeItem"; +import { localize } from "./utils/localize"; + +const cosmosDBTopLevelContextValues: string[] = [ + GraphAccountTreeItem.contextValue, + DocDBAccountTreeItem.contextValue, + TableAccountTreeItem.contextValue, + MongoAccountTreeItem.contextValue, +]; + +export async function activateInternal( + context: vscode.ExtensionContext, + perfStats: { loadStartTime: number; loadEndTime: number }, + ignoreBundle?: boolean +): Promise { + ext.context = context; + ext.ignoreBundle = ignoreBundle; + + ext.outputChannel = createAzExtOutputChannel("Azure Databases", ext.prefix); + context.subscriptions.push(ext.outputChannel); + registerUIExtensionVariables(ext); + registerAzureUtilsExtensionVariables(ext); + + await callWithTelemetryAndErrorHandling( + "cosmosDB.activate", + async (activateContext: IActionContext) => { + activateContext.telemetry.properties.isActivationEvent = "true"; + activateContext.telemetry.measurements.mainFileLoad = + (perfStats.loadEndTime - perfStats.loadStartTime) / 1000; + + ext.secretStorage = context.secrets; + + ext.rgApi = await getResourceGroupsApi(); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.AzureCosmosDb, + new DatabaseResolver() + ); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.PostgresqlServersStandard, + new DatabaseResolver() + ); + ext.rgApi.registerApplicationResourceResolver( + AzExtResourceType.PostgresqlServersFlexible, + new DatabaseResolver() + ); + + const workspaceRootTreeItem = ( + ext.rgApi.workspaceResourceTree as unknown as { + _rootTreeItem: AzExtParentTreeItem; + } + )._rootTreeItem; + const databaseWorkspaceProvider = new DatabaseWorkspaceProvider( + workspaceRootTreeItem + ); + ext.rgApi.registerWorkspaceResourceProvider( + "AttachedDatabaseAccount", + databaseWorkspaceProvider + ); + + ext.fileSystem = new DatabasesFileSystem(ext.rgApi.appResourceTree); + + registerDocDBCommands(); + registerGraphCommands(); + registerPostgresCommands(); + registerMongoCommands(); + + context.subscriptions.push( + vscode.workspace.registerFileSystemProvider( + DatabasesFileSystem.scheme, + ext.fileSystem + ) + ); + + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.selectSubscriptions", + () => + vscode.commands.executeCommand( + "azure-account.selectSubscriptions" + ) + ); + + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.createServer", + createServer + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteAccount", + deleteAccount + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.attachDatabaseAccount", + async (actionContext: IActionContext) => { + await ext.attachedAccountsNode.attachNewAccount( + actionContext + ); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.attachEmulator", + async (actionContext: IActionContext) => { + if (platform() !== "win32") { + actionContext.errorHandling.suppressReportIssue = true; + throw new Error( + localize( + "emulatorNotSupported", + "The Cosmos DB emulator is only supported on Windows." + ) + ); + } + + await ext.attachedAccountsNode.attachEmulator( + actionContext + ); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.refresh", + async (actionContext: IActionContext, node?: AzExtTreeItem) => { + if (node) { + await node.refresh(actionContext); + } else { + await ext.rgApi.appResourceTree.refresh( + actionContext, + node + ); + } + } + ); + + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.detachDatabaseAccount", + async ( + actionContext: IActionContext & ITreeItemPickerContext, + node?: AzExtTreeItem + ) => { + const children = + await ext.attachedAccountsNode.loadAllChildren( + actionContext + ); + if ( + children[0].contextValue === + "cosmosDBAttachDatabaseAccount" + ) { + const message = localize( + "noAttachedAccounts", + "There are no Attached Accounts." + ); + void vscode.window.showInformationMessage(message); + } else { + if (!node) { + node = + await ext.rgApi.workspaceResourceTree.showTreeItemPicker( + cosmosDBTopLevelContextValues.map( + (val: string) => + (val += AttachedAccountSuffix) + ), + actionContext + ); + } + if (node instanceof MongoAccountTreeItem) { + if ( + ext.connectedMongoDB && + node.fullId === + ext.connectedMongoDB.parent.fullId + ) { + setConnectedNode(undefined); + await node.refresh(actionContext); + } + } + await ext.attachedAccountsNode.detach(node); + await ext.rgApi.workspaceResourceTree.refresh( + actionContext, + ext.attachedAccountsNode + ); + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.importDocument", + async ( + actionContext: IActionContext, + selectedNode: + | vscode.Uri + | MongoCollectionTreeItem + | DocDBCollectionTreeItem, + uris: vscode.Uri[] + ) => { + if (selectedNode instanceof vscode.Uri) { + await importDocuments( + actionContext, + uris || [selectedNode], + undefined + ); + } else { + await importDocuments( + actionContext, + undefined, + selectedNode + ); + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.copyConnectionString", + cosmosDBCopyConnectionString + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openDocument", + async ( + actionContext: IActionContext, + node?: MongoDocumentTreeItem | DocDBDocumentTreeItem + ) => { + if (!node) { + node = await ext.rgApi.pickAppResource< + MongoDocumentTreeItem | DocDBDocumentTreeItem + >(actionContext, { + filter: [cosmosMongoFilter, sqlFilter], + expectedChildContextValue: [ + MongoDocumentTreeItem.contextValue, + DocDBDocumentTreeItem.contextValue, + ], + }); + } + + // Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619 + ext.fileSystem.fireChangedEvent(node); + await ext.fileSystem.showTextDocument(node); + }, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.update", + async (_actionContext: IActionContext, uri: vscode.Uri) => + await ext.fileSystem.updateWithoutPrompt(uri) + ); + registerCommandWithTreeNodeUnwrapping( + "azureDatabases.loadMore", + async (actionContext: IActionContext, node: AzExtTreeItem) => + await ext.rgApi.appResourceTree.loadMore( + node, + actionContext + ) + ); + registerEvent( + "cosmosDB.onDidChangeConfiguration", + vscode.workspace.onDidChangeConfiguration, + async ( + actionContext: IActionContext, + event: vscode.ConfigurationChangeEvent + ) => { + actionContext.telemetry.properties.isActivationEvent = + "true"; + actionContext.errorHandling.suppressDisplay = true; + if ( + event.affectsConfiguration( + ext.settingsKeys.documentLabelFields + ) + ) { + await vscode.commands.executeCommand( + "azureDatabases.refresh" + ); + } + } + ); + + // Suppress "Report an Issue" button for all errors in favor of the command + registerErrorHandler( + (c) => (c.errorHandling.suppressReportIssue = true) + ); + registerReportIssueCommand("azureDatabases.reportIssue"); + } + ); + + return createApiProvider([ + { + findTreeItem, + pickTreeItem, + revealTreeItem, + apiVersion: "1.2.0", + }, + ]); } // this method is called when your extension is deactivated export function deactivateInternal(): void { - // NOOP + // NOOP } -export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise { - if (!node) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context); - } +export async function createServer( + context: IActionContext, + node?: SubscriptionTreeItem +): Promise { + if (!node) { + node = + await ext.rgApi.appResourceTree.showTreeItemPicker( + SubscriptionTreeItem.contextValue, + context + ); + } - await SubscriptionTreeItem.createChild(context, node); + await SubscriptionTreeItem.createChild(context, node); } -export async function deleteAccount(context: IActionContext, node?: AzExtTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await deleteDatabaseAccount(context, node, false) +export async function deleteAccount( + context: IActionContext, + node?: AzExtTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter, + ], + }); + } + + await deleteDatabaseAccount(context, node, false); } -export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise { - const message = 'The connection string has been copied to the clipboard'; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - cosmosTableFilter, - cosmosGremlinFilter, - sqlFilter - ] - }); - } - - await vscode.env.clipboard.writeText(node.connectionString); - void vscode.window.showInformationMessage(message); +export async function cosmosDBCopyConnectionString( + context: IActionContext, + node?: MongoAccountTreeItem | DocDBAccountTreeItemBase +): Promise { + const message = "The connection string has been copied to the clipboard"; + if (!node) { + node = await ext.rgApi.pickAppResource< + MongoAccountTreeItem | DocDBAccountTreeItemBase + >(context, { + filter: [ + cosmosMongoFilter, + cosmosTableFilter, + cosmosGremlinFilter, + sqlFilter, + ], + }); + } + + await vscode.env.clipboard.writeText(node.connectionString); + void vscode.window.showInformationMessage(message); } diff --git a/Source/extensionVariables.ts b/Source/extensionVariables.ts index 4a3fc2650..3af61432c 100644 --- a/Source/extensionVariables.ts +++ b/Source/extensionVariables.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtOutputChannel } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeDataProvider, + AzExtTreeItem, + IAzExtOutputChannel, +} from "@microsoft/vscode-azext-utils"; import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { ExtensionContext, SecretStorage, TreeView } from "vscode"; import { DatabasesFileSystem } from "./DatabasesFileSystem"; @@ -19,33 +23,34 @@ import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWit * Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts */ export namespace ext { - export let connectedMongoDB: MongoDatabaseTreeItem | undefined; - export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; - export let context: ExtensionContext; - export let outputChannel: IAzExtOutputChannel; - export let tree: AzExtTreeDataProvider; - export let treeView: TreeView; - export let attachedAccountsNode: AttachedAccountsTreeItem; - export let ignoreBundle: boolean | undefined; - export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; - export let secretStorage: SecretStorage; - export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; - export const prefix: string = 'azureDatabases'; - export let fileSystem: DatabasesFileSystem; - export let mongoCodeLensProvider: MongoCodeLensProvider; - export let mongoLanguageClient: MongoDBLanguageClient; - export let rgApi: AzureHostExtensionApi; + export let connectedMongoDB: MongoDatabaseTreeItem | undefined; + export let connectedPostgresDB: PostgresDatabaseTreeItem | undefined; + export let context: ExtensionContext; + export let outputChannel: IAzExtOutputChannel; + export let tree: AzExtTreeDataProvider; + export let treeView: TreeView; + export let attachedAccountsNode: AttachedAccountsTreeItem; + export let ignoreBundle: boolean | undefined; + export let azureAccountTreeItem: AzureAccountTreeItemWithAttached; + export let secretStorage: SecretStorage; + export let postgresCodeLensProvider: PostgresCodeLensProvider | undefined; + export const prefix: string = "azureDatabases"; + export let fileSystem: DatabasesFileSystem; + export let mongoCodeLensProvider: MongoCodeLensProvider; + export let mongoLanguageClient: MongoDBLanguageClient; + export let rgApi: AzureHostExtensionApi; - export namespace settingsKeys { - export const mongoShellPath = 'mongo.shell.path'; - export const mongoShellArgs = 'mongo.shell.args'; - export const documentLabelFields = 'cosmosDB.documentLabelFields'; - export const enableEndpointDiscovery = 'cosmosDB.enableEndpointDiscovery'; - export const mongoShellTimeout = 'mongo.shell.timeout'; - export const batchSize = 'azureDatabases.batchSize'; + export namespace settingsKeys { + export const mongoShellPath = "mongo.shell.path"; + export const mongoShellArgs = "mongo.shell.args"; + export const documentLabelFields = "cosmosDB.documentLabelFields"; + export const enableEndpointDiscovery = + "cosmosDB.enableEndpointDiscovery"; + export const mongoShellTimeout = "mongo.shell.timeout"; + export const batchSize = "azureDatabases.batchSize"; - export namespace vsCode { - export const proxyStrictSSL = "http.proxyStrictSSL"; - } - } + export namespace vsCode { + export const proxyStrictSSL = "http.proxyStrictSSL"; + } + } } diff --git a/Source/getExtensionApi.ts b/Source/getExtensionApi.ts index bfd553e74..63efdb7e5 100644 --- a/Source/getExtensionApi.ts +++ b/Source/getExtensionApi.ts @@ -8,24 +8,35 @@ import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi"; import { Extension, extensions } from "vscode"; import { localize } from "./utils/localize"; -export async function getApiExport(extensionId: string): Promise { - const extension: Extension | undefined = extensions.getExtension(extensionId); - if (extension) { - if (!extension.isActive) { - await extension.activate(); - } +export async function getApiExport( + extensionId: string +): Promise { + const extension: Extension | undefined = + extensions.getExtension(extensionId); + if (extension) { + if (!extension.isActive) { + await extension.activate(); + } - return extension.exports; - } + return extension.exports; + } - return undefined; + return undefined; } export async function getResourceGroupsApi(): Promise { - const rgApiProvider = await getApiExport('ms-azuretools.vscode-azureresourcegroups'); - if (rgApiProvider) { - return rgApiProvider.getApi('0.0.1'); - } else { - throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension')); - } + const rgApiProvider = + await getApiExport( + "ms-azuretools.vscode-azureresourcegroups" + ); + if (rgApiProvider) { + return rgApiProvider.getApi("0.0.1"); + } else { + throw new Error( + localize( + "noResourceGroupExt", + "Could not find the Azure Resource Groups extension" + ) + ); + } } diff --git a/Source/vscode-cosmosdb.api.d.ts b/Source/vscode-cosmosdb.api.d.ts index d5e4416c1..4e813c5e5 100644 --- a/Source/vscode-cosmosdb.api.d.ts +++ b/Source/vscode-cosmosdb.api.d.ts @@ -4,93 +4,103 @@ *--------------------------------------------------------------------------------------------*/ export interface AzureDatabasesExtensionApi { - apiVersion: string; - - /** - * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. - * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. - * - * @param query The query object to use for the find - */ - findTreeItem(query: TreeItemQuery): Promise; - - /** - * Prompts the user to pick an item from the Azure Databases tree - * - * @param options Configures the behavior of the tree item picker - */ - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'DatabaseAccount' }): Promise; - pickTreeItem(options: PickTreeItemOptions & { resourceType: 'Database' }): Promise; - - /** - * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string - */ - revealTreeItem(resourceId: string): Promise; + apiVersion: string; + + /** + * Finds the first matching item in the Azure Databases tree, or otherwise returns undefined. + * NOTE: The item may not actually be loaded/attached in the tree until 'reveal' is called. + * + * @param query The query object to use for the find + */ + findTreeItem( + query: TreeItemQuery + ): Promise; + + /** + * Prompts the user to pick an item from the Azure Databases tree + * + * @param options Configures the behavior of the tree item picker + */ + pickTreeItem( + options: PickTreeItemOptions & { resourceType: "DatabaseAccount" } + ): Promise; + pickTreeItem( + options: PickTreeItemOptions & { resourceType: "Database" } + ): Promise; + + /** + * Simpler version of `AzureDatabasesTreeItem.reveal` based on the `resourceId` instead of querying based on a connection string + */ + revealTreeItem(resourceId: string): Promise; } export interface AzureDatabasesTreeItem { - /** - * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. - */ - reveal(): Promise; + /** + * Reveals the item in the tree. This may result in loading more Azure Databases tree items or manually attaching by connection string. + */ + reveal(): Promise; } export interface DatabaseAccountTreeItem extends AzureDatabasesTreeItem { - hostName: string; - port: string; - connectionString: string; - - /** - * Data specific to Azure or undefined if the resource is not in Azure. - */ - azureData?: { - accountName: string; - accountId: string; - } - - docDBData?: { - masterKey: string; - documentEndpoint: string; - } - - postgresData?: { - username: string | undefined; - password: string | undefined; - } - + hostName: string; + port: string; + connectionString: string; + + /** + * Data specific to Azure or undefined if the resource is not in Azure. + */ + azureData?: { + accountName: string; + accountId: string; + }; + + docDBData?: { + masterKey: string; + documentEndpoint: string; + }; + + postgresData?: { + username: string | undefined; + password: string | undefined; + }; } export interface DatabaseTreeItem extends DatabaseAccountTreeItem { - databaseName: string; + databaseName: string; } -export type AzureDatabasesResourceType = 'DatabaseAccount' | 'Database'; +export type AzureDatabasesResourceType = "DatabaseAccount" | "Database"; -export type AzureDatabasesApiType = 'Mongo' | 'SQL' | 'Graph' | 'Table' | 'Postgres'; +export type AzureDatabasesApiType = + | "Mongo" + | "SQL" + | "Graph" + | "Table" + | "Postgres"; export interface PickTreeItemOptions { - /** - * The resource type of the picked item - */ - resourceType: AzureDatabasesResourceType; - - /** - * An array of the API types that can be picked, or undefined if all API types are allowed - */ - apiType?: AzureDatabasesApiType[]; + /** + * The resource type of the picked item + */ + resourceType: AzureDatabasesResourceType; + + /** + * An array of the API types that can be picked, or undefined if all API types are allowed + */ + apiType?: AzureDatabasesApiType[]; } export interface TreeItemQuery { - /** - * An account or database connection string - */ - connectionString?: string; - - postgresData?: { - hostName: string; - port: string; - databaseName: string | undefined; - username: string | undefined; - password: string | undefined; - } + /** + * An account or database connection string + */ + connectionString?: string; + + postgresData?: { + hostName: string; + port: string; + databaseName: string | undefined; + username: string | undefined; + password: string | undefined; + }; } diff --git a/Source/vscode-cosmosdbgraph.api.d.ts b/Source/vscode-cosmosdbgraph.api.d.ts index 95cde2531..bf8d4c769 100644 --- a/Source/vscode-cosmosdbgraph.api.d.ts +++ b/Source/vscode-cosmosdbgraph.api.d.ts @@ -4,26 +4,26 @@ *--------------------------------------------------------------------------------------------*/ export interface CosmosDBGraphExtensionApi { - apiVersion: string; + apiVersion: string; - openGraphExplorer(config: IGraphConfiguration): Promise; + openGraphExplorer(config: IGraphConfiguration): Promise; } export interface IGremlinEndpoint { - host: string; - port: number; - ssl: boolean; + host: string; + port: number; + ssl: boolean; } export interface IGraphConfiguration { - // e.g. https://graphaccount.documents.azure.com:443 - documentEndpoint: string; + // e.g. https://graphaccount.documents.azure.com:443 + documentEndpoint: string; - gremlinEndpoint?: IGremlinEndpoint; - possibleGremlinEndpoints: IGremlinEndpoint[]; + gremlinEndpoint?: IGremlinEndpoint; + possibleGremlinEndpoints: IGremlinEndpoint[]; - key: string; - databaseName: string; - graphName: string; - tabTitle: string; + key: string; + databaseName: string; + graphName: string; + tabTitle: string; } diff --git a/build/vscode-languageserver-files-stub.js b/build/vscode-languageserver-files-stub.js index b7e70019f..568f06348 100644 --- a/build/vscode-languageserver-files-stub.js +++ b/build/vscode-languageserver-files-stub.js @@ -10,7 +10,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const url = require("url"); const path = require("path"); @@ -21,25 +21,25 @@ const child_process_1 = require("child_process"); * complete implementation of handling VS Code URIs. */ function uriToFilePath(uri) { - let parsed = url.parse(uri); - if (parsed.protocol !== 'file:' || !parsed.path) { - return undefined; - } - let segments = parsed.path.split('/'); - for (var i = 0, len = segments.length; i < len; i++) { - segments[i] = decodeURIComponent(segments[i]); - } - if (process.platform === 'win32' && segments.length > 1) { - let first = segments[0]; - let second = segments[1]; - // Do we have a drive letter and we started with a / which is the - // case if the first segement is empty (see split above) - if (first.length === 0 && second.length > 1 && second[1] === ':') { - // Remove first slash - segments.shift(); - } - } - return path.normalize(segments.join('/')); + let parsed = url.parse(uri); + if (parsed.protocol !== "file:" || !parsed.path) { + return undefined; + } + let segments = parsed.path.split("/"); + for (var i = 0, len = segments.length; i < len; i++) { + segments[i] = decodeURIComponent(segments[i]); + } + if (process.platform === "win32" && segments.length > 1) { + let first = segments[0]; + let second = segments[1]; + // Do we have a drive letter and we started with a / which is the + // case if the first segement is empty (see split above) + if (first.length === 0 && second.length > 1 && second[1] === ":") { + // Remove first slash + segments.shift(); + } + } + return path.normalize(segments.join("/")); } exports.uriToFilePath = uriToFilePath; @@ -47,26 +47,26 @@ exports.uriToFilePath = uriToFilePath; // Throw NYI if any of the other functions are ever called (they shouldn't be currently) function resolveModule(workspaceRoot, moduleName) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModule = resolveModule; function resolve(moduleName, nodePath, cwd, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolve = resolve; function resolveGlobalNodePath(tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveGlobalNodePath = resolveGlobalNodePath; function resolveGlobalYarnPath(tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveGlobalYarnPath = resolveGlobalYarnPath; function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModulePath = resolveModulePath; function resolveModule2(workspaceRoot, moduleName, nodePath, tracer) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } exports.resolveModule2 = resolveModule2; diff --git a/grammar/JavaScript.tmLanguage.json b/grammar/JavaScript.tmLanguage.json index 71207a7b3..4928616c4 100644 --- a/grammar/JavaScript.tmLanguage.json +++ b/grammar/JavaScript.tmLanguage.json @@ -1,3713 +1,3711 @@ { - "name.$comment": "** Changed **", - "name": "Mongo Scrapbooks (JavaScript)", - "scopeName.$comment": "** Changed **", - "scopeName": "source.mongo.js", - "fileTypes.$comment": "** Changed from .js/.jsx **", - "fileTypes": [ - ".mongo" - ], - "uuid.$comment": "** Changed **", - "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", - "patterns": [ - { - "include": "#directives" - }, - { - "include": "#statements" - }, - { - "name": "comment.line.shebang.ts", - "match": "\\A(#!).*(?=$)", - "captures": { - "1": { - "name": "punctuation.definition.comment.ts" - } - } - } - ], - "repository": { - "statements": { - "patterns": [ - { - "include": "#string" - }, - { - "include": "#template" - }, - { - "include": "#comment" - }, - { - "include": "#declaration" - }, - { - "include": "#switch-statement" - }, - { - "include": "#for-loop" - }, - { - "include": "#after-operator-block" - }, - { - "include": "#decl-block" - }, - { - "include": "#control-statement" - }, - { - "include": "#expression" - }, - { - "include": "#punctuation-semicolon" - } - ] - }, - "var-expr": { - "name": "meta.var.expr.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js entity.name.function.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.constant.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.readwrite.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - } - ] - }, - "var-single-variable-type-annotation": { - "patterns": [ - { - "include": "#type-annotation" - }, - { - "include": "#string" - }, - { - "include": "#comment" - } - ] - }, - "destructuring-variable": { - "patterns": [ - { - "name": "meta.object-binding-pattern-variable.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" - }, - { - "name": "meta.definition.property.js variable.object.property.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.js", - "match": "\\?" - } - ] - } - ] - }, - "method-declaration": { - "name": "meta.method.declaration.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "captures": { - "1": { - "name": "storage.modifier.js" - }, - "2": { - "name": "keyword.operator.rest.js" - }, - "3": { - "name": "entity.name.function.js" - }, - "4": { - "name": "keyword.operator.optional.js" - } - } - }, - { - "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type" - } - ] - }, - "type": { - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#string" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#type-primitive" - }, - { - "include": "#type-builtin-literals" - }, - { - "include": "#type-parameters" - }, - { - "include": "#type-tuple" - }, - { - "include": "#type-object" - }, - { - "include": "#type-operators" - }, - { - "include": "#type-fn-type-parameters" - }, - { - "include": "#type-paren-or-function-parameters" - }, - { - "include": "#type-function-return-type" - }, - { - "include": "#type-name" - } - ] - }, - "function-parameters": { - "name": "meta.parameters.js", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#decorator" - }, - { - "include": "#destructuring-parameter" - }, - { - "include": "#parameter-name" - }, - { - "include": "#type-annotation" - }, - { - "include": "#variable-initializer" - }, - { - "name": "punctuation.separator.parameter.js", - "match": "," - } - ] - }, - "type-primitive": { - "name": "support.type.primitive.js", - "match": "(?)\n ))\n )\n )\n)", - "end": "(?<=\\))", - "patterns": [ - { - "include": "#function-parameters" - } - ] - } - ] - }, - "type-operators": { - "patterns": [ - { - "include": "#typeof-operator" - }, - { - "name": "keyword.operator.type.js", - "match": "[&|]" - }, - { - "name": "keyword.operator.expression.keyof.js", - "match": "(?", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", - "patterns": [ - { - "include": "#comment" - }, - { - "name": "meta.object.type.js", - "begin": "(?<==>)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "type-tuple": { - "name": "meta.type.tuple.js", - "begin": "\\[", - "beginCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "type-name": { - "patterns": [ - { - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", - "captures": { - "1": { - "name": "entity.name.type.module.js" - }, - "2": { - "name": "punctuation.accessor.js" - } - } - }, - { - "name": "entity.name.type.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "type-parameters": { - "name": "meta.type.parameters.js", - "begin": "(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "(?=$)|(>)", - "endCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "name": "storage.modifier.js", - "match": "(?)" - }, - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "variable-initializer": { - "patterns": [ - { - "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "support.constant.dom.js" - }, - "3": { - "name": "support.variable.property.dom.js" - } - } - }, - { - "name": "support.class.node.js", - "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", - "patterns": [ - { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "entity.name.function.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - }, - { - "include": "#comment" - }, - { - "name": "meta.type.parameters.js", - "begin": "\\<", - "beginCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "\\>", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - { - "include": "#paren-expression" - } - ] - }, - "identifiers": { - "patterns": [ - { - "include": "#object-identifiers" - }, - { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "entity.name.function.js" - } - } - }, - { - "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.property.js" - } - } - }, - { - "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.property.js" - } - } - }, - { - "name": "variable.other.constant.js", - "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" - }, - { - "name": "variable.other.readwrite.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "object-identifiers": { - "patterns": [ - { - "name": "support.class.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" - }, - { - "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.object.property.js" - }, - "3": { - "name": "variable.other.object.property.js" - } - } - }, - { - "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "variable.other.constant.object.js" - }, - "2": { - "name": "variable.other.object.js" - } - } - } - ] - }, - "cast": { - "patterns": [ - { - "include": "#jsx" - } - ] - }, - "new-expr": { - "name": "new.expr.js", - "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "entity.name.function.js" - }, - "2": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "\\.\\.\\.", - "beginCaptures": { - "0": { - "name": "keyword.operator.spread.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", - "captures": { - "1": { - "name": "variable.other.readwrite.js" - } - } - }, - { - "include": "#punctuation-comma" - } - ] - }, - "expression-operators": { - "patterns": [ - { - "name": "keyword.control.flow.js", - "match": "(?>=|>>>=|\\|=" - }, - { - "name": "keyword.operator.bitwise.shift.js", - "match": "<<|>>>|>>" - }, - { - "name": "keyword.operator.comparison.js", - "match": "===|!==|==|!=" - }, - { - "name": "keyword.operator.relational.js", - "match": "<=|>=|<>|<|>" - }, - { - "name": "keyword.operator.logical.js", - "match": "\\!|&&|\\|\\|" - }, - { - "name": "keyword.operator.bitwise.js", - "match": "\\&|~|\\^|\\|" - }, - { - "name": "keyword.operator.assignment.js", - "match": "\\=" - }, - { - "name": "keyword.operator.decrement.js", - "match": "--" - }, - { - "name": "keyword.operator.increment.js", - "match": "\\+\\+" - }, - { - "name": "keyword.operator.arithmetic.js", - "match": "%|\\*|/|-|\\+" - }, - { - "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", - "captures": { - "1": { - "name": "keyword.operator.arithmetic.js" - } - } - } - ] - }, - "typeof-operator": { - "name": "keyword.operator.expression.typeof.js", - "match": "(?)", - "captures": { - "1": { - "name": "storage.modifier.async.js" - }, - "2": { - "name": "variable.parameter.js" - } - } - }, - { - "name": "meta.arrow.js", - "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type-parameters" - }, - { - "include": "#function-parameters" - }, - { - "include": "#arrow-return-type" - } - ] - }, - { - "name": "meta.arrow.js", - "begin": "=>", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?<=\\})|((?!\\{)(?=\\S))", - "patterns": [ - { - "include": "#decl-block" - }, - { - "include": "#expression" - } - ] - } - ] - }, - "arrow-return-type": { - "name": "meta.return.type.arrow.js", - "begin": "(?<=\\))\\s*(:)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "name": "meta.object.type.js", - "begin": "(?<=:)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "punctuation-comma": { - "name": "punctuation.separator.comma.js", - "match": "," - }, - "punctuation-semicolon": { - "name": "punctuation.terminator.statement.js", - "match": ";" - }, - "punctuation-accessor": { - "name": "punctuation.accessor.js", - "match": "\\." - }, - "paren-expression": { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "patterns": [ - { - "include": "#expression" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "qstring-double": { - "name": "string.quoted.double.js", - "begin": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\")|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "qstring-single": { - "name": "string.quoted.single.js", - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\\')|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "regex": { - "patterns": [ - { - "name": "string.regexp.js", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(/)([gimuy]*)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "keyword.other.js" - } - }, - "patterns": [ - { - "include": "#regexp" - } - ] - }, - { - "name": "string.regexp.js", - "begin": "(?\\s*$)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.js" - } - }, - "end": "(?=$)", - "patterns": [ - { - "name": "meta.tag.js", - "begin": "(<)(reference|amd-dependency|amd-module)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.directive.js" - }, - "2": { - "name": "entity.name.tag.directive.js" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.directive.js" - } - }, - "patterns": [ - { - "name": "entity.other.attribute-name.directive.js", - "match": "path|types|no-default-lib|name" - }, - { - "name": "keyword.operator.assignment.js", - "match": "=" - }, - { - "include": "#string" - } - ] - } - ] - }, - "docblock": { - "patterns": [ - { - "name": "storage.type.class.jsdoc", - "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "variable.other.jsdoc" - }, - "3": { - "name": "other.description.jsdoc" - } - } - }, - { - "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "other.description.jsdoc" - } - } - } - ] - }, - "jsx-tag-attributes": { - "patterns": [ - { - "include": "#jsx-tag-attribute-name" - }, - { - "include": "#jsx-tag-attribute-assignment" - }, - { - "include": "#jsx-string-double-quoted" - }, - { - "include": "#jsx-string-single-quoted" - }, - { - "include": "#jsx-evaluated-code" - } - ] - }, - "jsx-tag-attribute-name": { - "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", - "captures": { - "1": { - "name": "entity.other.attribute-name.js" - } - } - }, - "jsx-tag-attribute-assignment": { - "name": "keyword.operator.assignment.js", - "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" - }, - "jsx-string-double-quoted": { - "name": "string.quoted.double.js", - "begin": "\"", - "end": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-string-single-quoted": { - "name": "string.quoted.single.js", - "begin": "'", - "end": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-entities": { - "patterns": [ - { - "name": "constant.character.entity.js", - "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", - "captures": { - "1": { - "name": "punctuation.definition.entity.js" - }, - "3": { - "name": "punctuation.definition.entity.js" - } - } - }, - { - "name": "invalid.illegal.bad-ampersand.js", - "match": "&" - } - ] - }, - "jsx-evaluated-code": { - "name": "meta.embedded.expression.js", - "begin": "\\{", - "end": "\\}", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.js" - } - }, - "patterns": [ - { - "include": "#expression" - } - ] - }, - "jsx-tag-attributes-illegal": { - "name": "invalid.illegal.attribute.js", - "match": "\\S+" - }, - "jsx-tag-without-attributes": { - "name": "meta.tag.without-attributes.js", - "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", - "end": "()", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "endCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "contentName": "meta.jsx.children.tsx", - "patterns": [ - { - "include": "#jsx-children" - } - ] - }, - "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-child-tag": { - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-tag": { - "name": "meta.tag.js", - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(?=(/>)|(?:()))", - "patterns": [ - { - "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - } - }, - "end": "(?=[/]?>)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#jsx-tag-attributes" - }, - { - "include": "#jsx-tag-attributes-illegal" - } - ] - }, - { - "begin": "(>)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.end.js" - } - }, - "end": "(?=" - }, - "jsx-children": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-child-tag" - }, - { - "include": "#jsx-tag-invalid" - }, - { - "include": "#jsx-evaluated-code" - }, - { - "include": "#jsx-entities" - } - ] - }, - "jsx": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-tag-in-expression" - }, - { - "include": "#jsx-tag-invalid" - } - ] - } - }, - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" + "name.$comment": "** Changed **", + "name": "Mongo Scrapbooks (JavaScript)", + "scopeName.$comment": "** Changed **", + "scopeName": "source.mongo.js", + "fileTypes.$comment": "** Changed from .js/.jsx **", + "fileTypes": [".mongo"], + "uuid.$comment": "** Changed **", + "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", + "patterns": [ + { + "include": "#directives" + }, + { + "include": "#statements" + }, + { + "name": "comment.line.shebang.ts", + "match": "\\A(#!).*(?=$)", + "captures": { + "1": { + "name": "punctuation.definition.comment.ts" + } + } + } + ], + "repository": { + "statements": { + "patterns": [ + { + "include": "#string" + }, + { + "include": "#template" + }, + { + "include": "#comment" + }, + { + "include": "#declaration" + }, + { + "include": "#switch-statement" + }, + { + "include": "#for-loop" + }, + { + "include": "#after-operator-block" + }, + { + "include": "#decl-block" + }, + { + "include": "#control-statement" + }, + { + "include": "#expression" + }, + { + "include": "#punctuation-semicolon" + } + ] + }, + "var-expr": { + "name": "meta.var.expr.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js entity.name.function.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + }, + { + "name": "meta.var-single-variable.expr.js", + "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js variable.other.constant.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + }, + { + "name": "meta.var-single-variable.expr.js", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)", + "beginCaptures": { + "1": { + "name": "meta.definition.variable.js variable.other.readwrite.js" + } + }, + "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", + "patterns": [ + { + "include": "#var-single-variable-type-annotation" + } + ] + } + ] + }, + "var-single-variable-type-annotation": { + "patterns": [ + { + "include": "#type-annotation" + }, + { + "include": "#string" + }, + { + "include": "#comment" + } + ] + }, + "destructuring-variable": { + "patterns": [ + { + "name": "meta.object-binding-pattern-variable.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" + }, + { + "name": "meta.definition.property.js variable.object.property.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.js", + "match": "\\?" + } + ] + } + ] + }, + "method-declaration": { + "name": "meta.method.declaration.js", + "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", + "captures": { + "1": { + "name": "storage.modifier.js" + }, + "2": { + "name": "keyword.operator.rest.js" + }, + "3": { + "name": "entity.name.function.js" + }, + "4": { + "name": "keyword.operator.optional.js" + } + } + }, + { + "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type" + } + ] + }, + "type": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#string" + }, + { + "include": "#numeric-literal" + }, + { + "include": "#type-primitive" + }, + { + "include": "#type-builtin-literals" + }, + { + "include": "#type-parameters" + }, + { + "include": "#type-tuple" + }, + { + "include": "#type-object" + }, + { + "include": "#type-operators" + }, + { + "include": "#type-fn-type-parameters" + }, + { + "include": "#type-paren-or-function-parameters" + }, + { + "include": "#type-function-return-type" + }, + { + "include": "#type-name" + } + ] + }, + "function-parameters": { + "name": "meta.parameters.js", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.js" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.js" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#decorator" + }, + { + "include": "#destructuring-parameter" + }, + { + "include": "#parameter-name" + }, + { + "include": "#type-annotation" + }, + { + "include": "#variable-initializer" + }, + { + "name": "punctuation.separator.parameter.js", + "match": "," + } + ] + }, + "type-primitive": { + "name": "support.type.primitive.js", + "match": "(?)\n ))\n )\n )\n)", + "end": "(?<=\\))", + "patterns": [ + { + "include": "#function-parameters" + } + ] + } + ] + }, + "type-operators": { + "patterns": [ + { + "include": "#typeof-operator" + }, + { + "name": "keyword.operator.type.js", + "match": "[&|]" + }, + { + "name": "keyword.operator.expression.keyof.js", + "match": "(?", + "beginCaptures": { + "0": { + "name": "storage.type.function.arrow.js" + } + }, + "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", + "patterns": [ + { + "include": "#comment" + }, + { + "name": "meta.object.type.js", + "begin": "(?<==>)\\s*(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.block.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.js" + } + }, + "patterns": [ + { + "include": "#type-object-members" + } + ] + }, + { + "include": "#type-predicate-operator" + }, + { + "include": "#type" + } + ] + }, + "type-tuple": { + "name": "meta.type.tuple.js", + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "patterns": [ + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "type-name": { + "patterns": [ + { + "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", + "captures": { + "1": { + "name": "entity.name.type.module.js" + }, + "2": { + "name": "punctuation.accessor.js" + } + } + }, + { + "name": "entity.name.type.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + } + ] + }, + "type-parameters": { + "name": "meta.type.parameters.js", + "begin": "(<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.begin.js" + } + }, + "end": "(?=$)|(>)", + "endCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.end.js" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "name": "storage.modifier.js", + "match": "(?)" + }, + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "variable-initializer": { + "patterns": [ + { + "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "support.constant.dom.js" + }, + "3": { + "name": "support.variable.property.dom.js" + } + } + }, + { + "name": "support.class.node.js", + "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", + "patterns": [ + { + "include": "#literal" + }, + { + "include": "#support-objects" + }, + { + "include": "#object-identifiers" + }, + { + "include": "#punctuation-accessor" + }, + { + "name": "entity.name.function.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + }, + { + "include": "#comment" + }, + { + "name": "meta.type.parameters.js", + "begin": "\\<", + "beginCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.begin.js" + } + }, + "end": "\\>", + "endCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.end.js" + } + }, + "patterns": [ + { + "include": "#type" + }, + { + "include": "#punctuation-comma" + } + ] + }, + { + "include": "#paren-expression" + } + ] + }, + "identifiers": { + "patterns": [ + { + "include": "#object-identifiers" + }, + { + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "entity.name.function.js" + } + } + }, + { + "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.constant.property.js" + } + } + }, + { + "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.property.js" + } + } + }, + { + "name": "variable.other.constant.js", + "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" + }, + { + "name": "variable.other.readwrite.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + } + ] + }, + "object-identifiers": { + "patterns": [ + { + "name": "support.class.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" + }, + { + "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.accessor.js" + }, + "2": { + "name": "variable.other.constant.object.property.js" + }, + "3": { + "name": "variable.other.object.property.js" + } + } + }, + { + "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", + "captures": { + "1": { + "name": "variable.other.constant.object.js" + }, + "2": { + "name": "variable.other.object.js" + } + } + } + ] + }, + "cast": { + "patterns": [ + { + "include": "#jsx" + } + ] + }, + "new-expr": { + "name": "new.expr.js", + "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", + "beginCaptures": { + "0": { + "name": "meta.object-literal.key.js" + }, + "1": { + "name": "entity.name.function.js" + }, + "2": { + "name": "punctuation.separator.key-value.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", + "beginCaptures": { + "0": { + "name": "meta.object-literal.key.js" + }, + "1": { + "name": "punctuation.separator.key-value.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "begin": "\\.\\.\\.", + "beginCaptures": { + "0": { + "name": "keyword.operator.spread.js" + } + }, + "end": "(?=,|\\})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "name": "meta.object.member.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", + "captures": { + "1": { + "name": "variable.other.readwrite.js" + } + } + }, + { + "include": "#punctuation-comma" + } + ] + }, + "expression-operators": { + "patterns": [ + { + "name": "keyword.control.flow.js", + "match": "(?>=|>>>=|\\|=" + }, + { + "name": "keyword.operator.bitwise.shift.js", + "match": "<<|>>>|>>" + }, + { + "name": "keyword.operator.comparison.js", + "match": "===|!==|==|!=" + }, + { + "name": "keyword.operator.relational.js", + "match": "<=|>=|<>|<|>" + }, + { + "name": "keyword.operator.logical.js", + "match": "\\!|&&|\\|\\|" + }, + { + "name": "keyword.operator.bitwise.js", + "match": "\\&|~|\\^|\\|" + }, + { + "name": "keyword.operator.assignment.js", + "match": "\\=" + }, + { + "name": "keyword.operator.decrement.js", + "match": "--" + }, + { + "name": "keyword.operator.increment.js", + "match": "\\+\\+" + }, + { + "name": "keyword.operator.arithmetic.js", + "match": "%|\\*|/|-|\\+" + }, + { + "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", + "captures": { + "1": { + "name": "keyword.operator.arithmetic.js" + } + } + } + ] + }, + "typeof-operator": { + "name": "keyword.operator.expression.typeof.js", + "match": "(?)", + "captures": { + "1": { + "name": "storage.modifier.async.js" + }, + "2": { + "name": "variable.parameter.js" + } + } + }, + { + "name": "meta.arrow.js", + "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", + "beginCaptures": { + "1": { + "name": "storage.modifier.async.js" + } + }, + "end": "(?==>|\\{)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type-parameters" + }, + { + "include": "#function-parameters" + }, + { + "include": "#arrow-return-type" + } + ] + }, + { + "name": "meta.arrow.js", + "begin": "=>", + "beginCaptures": { + "0": { + "name": "storage.type.function.arrow.js" + } + }, + "end": "(?<=\\})|((?!\\{)(?=\\S))", + "patterns": [ + { + "include": "#decl-block" + }, + { + "include": "#expression" + } + ] + } + ] + }, + "arrow-return-type": { + "name": "meta.return.type.arrow.js", + "begin": "(?<=\\))\\s*(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.js" + } + }, + "end": "(?==>|\\{)", + "patterns": [ + { + "name": "meta.object.type.js", + "begin": "(?<=:)\\s*(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.block.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.js" + } + }, + "patterns": [ + { + "include": "#type-object-members" + } + ] + }, + { + "include": "#type-predicate-operator" + }, + { + "include": "#type" + } + ] + }, + "punctuation-comma": { + "name": "punctuation.separator.comma.js", + "match": "," + }, + "punctuation-semicolon": { + "name": "punctuation.terminator.statement.js", + "match": ";" + }, + "punctuation-accessor": { + "name": "punctuation.accessor.js", + "match": "\\." + }, + "paren-expression": { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "meta.brace.round.js" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "meta.brace.round.js" + } + }, + "patterns": [ + { + "include": "#expression" + }, + { + "include": "#punctuation-comma" + } + ] + }, + "qstring-double": { + "name": "string.quoted.double.js", + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(\")|((?:[^\\\\\\n])$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "invalid.illegal.newline.js" + } + }, + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "qstring-single": { + "name": "string.quoted.single.js", + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(\\')|((?:[^\\\\\\n])$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "invalid.illegal.newline.js" + } + }, + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "regex": { + "patterns": [ + { + "name": "string.regexp.js", + "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "(/)([gimuy]*)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.js" + }, + "2": { + "name": "keyword.other.js" + } + }, + "patterns": [ + { + "include": "#regexp" + } + ] + }, + { + "name": "string.regexp.js", + "begin": "(?\\s*$)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.js" + } + }, + "end": "(?=$)", + "patterns": [ + { + "name": "meta.tag.js", + "begin": "(<)(reference|amd-dependency|amd-module)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.directive.js" + }, + "2": { + "name": "entity.name.tag.directive.js" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.directive.js" + } + }, + "patterns": [ + { + "name": "entity.other.attribute-name.directive.js", + "match": "path|types|no-default-lib|name" + }, + { + "name": "keyword.operator.assignment.js", + "match": "=" + }, + { + "include": "#string" + } + ] + } + ] + }, + "docblock": { + "patterns": [ + { + "name": "storage.type.class.jsdoc", + "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", + "captures": { + "0": { + "name": "other.meta.jsdoc" + }, + "1": { + "name": "entity.name.type.instance.jsdoc" + }, + "2": { + "name": "variable.other.jsdoc" + }, + "3": { + "name": "other.description.jsdoc" + } + } + }, + { + "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", + "captures": { + "0": { + "name": "other.meta.jsdoc" + }, + "1": { + "name": "entity.name.type.instance.jsdoc" + }, + "2": { + "name": "other.description.jsdoc" + } + } + } + ] + }, + "jsx-tag-attributes": { + "patterns": [ + { + "include": "#jsx-tag-attribute-name" + }, + { + "include": "#jsx-tag-attribute-assignment" + }, + { + "include": "#jsx-string-double-quoted" + }, + { + "include": "#jsx-string-single-quoted" + }, + { + "include": "#jsx-evaluated-code" + } + ] + }, + "jsx-tag-attribute-name": { + "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", + "captures": { + "1": { + "name": "entity.other.attribute-name.js" + } + } + }, + "jsx-tag-attribute-assignment": { + "name": "keyword.operator.assignment.js", + "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" + }, + "jsx-string-double-quoted": { + "name": "string.quoted.double.js", + "begin": "\"", + "end": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-string-single-quoted": { + "name": "string.quoted.single.js", + "begin": "'", + "end": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-entities": { + "patterns": [ + { + "name": "constant.character.entity.js", + "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", + "captures": { + "1": { + "name": "punctuation.definition.entity.js" + }, + "3": { + "name": "punctuation.definition.entity.js" + } + } + }, + { + "name": "invalid.illegal.bad-ampersand.js", + "match": "&" + } + ] + }, + "jsx-evaluated-code": { + "name": "meta.embedded.expression.js", + "begin": "\\{", + "end": "\\}", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.js" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.js" + } + }, + "patterns": [ + { + "include": "#expression" + } + ] + }, + "jsx-tag-attributes-illegal": { + "name": "invalid.illegal.attribute.js", + "match": "\\S+" + }, + "jsx-tag-without-attributes": { + "name": "meta.tag.without-attributes.js", + "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", + "end": "()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "contentName": "meta.jsx.children.tsx", + "patterns": [ + { + "include": "#jsx-children" + } + ] + }, + "jsx-tag-in-expression": { + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(/>)|(?:())", + "endCaptures": { + "0": { + "name": "meta.tag.js" + }, + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "entity.name.tag.js" + }, + "4": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-tag" + } + ] + }, + "jsx-child-tag": { + "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(/>)|(?:())", + "endCaptures": { + "0": { + "name": "meta.tag.js" + }, + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "entity.name.tag.js" + }, + "4": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#jsx-tag" + } + ] + }, + "jsx-tag": { + "name": "meta.tag.js", + "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "end": "(?=(/>)|(?:()))", + "patterns": [ + { + "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + } + }, + "end": "(?=[/]?>)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#jsx-tag-attributes" + }, + { + "include": "#jsx-tag-attributes-illegal" + } + ] + }, + { + "begin": "(>)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + } + }, + "end": "(?=" + }, + "jsx-children": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-child-tag" + }, + { + "include": "#jsx-tag-invalid" + }, + { + "include": "#jsx-evaluated-code" + }, + { + "include": "#jsx-entities" + } + ] + }, + "jsx": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-tag-in-expression" + }, + { + "include": "#jsx-tag-invalid" + } + ] + } + }, + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" } diff --git a/grammar/Readme.md b/grammar/Readme.md index 7d4d7ce13..27fac0582 100644 --- a/grammar/Readme.md +++ b/grammar/Readme.md @@ -1,10 +1,13 @@ -Note: The file `JavaScript.tmLanguage.json` is derived from [TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). +Note: The file `JavaScript.tmLanguage.json` is derived from +[TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). # To update the grammar after making changes: 1. npm run update-grammar -2. Re-comment imports in mongoParser.ts that are not used and cause compile errors +2. Re-comment imports in mongoParser.ts that are not used and cause compile + errors # Debugging the grammar -See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to generate the debug info before trying to launch. +See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to +generate the debug info before trying to launch. diff --git a/grammar/configuration.json b/grammar/configuration.json index 42f2e2c1b..82ae3324e 100644 --- a/grammar/configuration.json +++ b/grammar/configuration.json @@ -1,55 +1,39 @@ { - "comments": { - "lineComment": "//", - "blockComment": [ - "/*", - "*/" - ] - }, - "brackets": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ] - ], - "autoClosingPairs": [ - { - "open": "{", - "close": "}" - }, - { - "open": "[", - "close": "]" - }, - { - "open": "(", - "close": ")" - }, - { - "open": "'", - "close": "'", - "notIn": [ - "string", - "comment" - ] - }, - { - "open": "\"", - "close": "\"", - "notIn": [ - "string" - ] - }, - { - "open": "/**", - "close": " */", - "notIn": [ - "string" - ] - } - ] + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"] + ], + "autoClosingPairs": [ + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "'", + "close": "'", + "notIn": ["string", "comment"] + }, + { + "open": "\"", + "close": "\"", + "notIn": ["string"] + }, + { + "open": "/**", + "close": " */", + "notIn": ["string"] + } + ] } From bd1f9419b8ef975f5bf816b0618f92bdfdb68e6c Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Wed, 22 Nov 2023 10:38:11 +0200 Subject: [PATCH 26/33] squash! --- .../api/DatabaseAccountTreeItemInternal.ts | 220 +- .../commands/api/DatabaseTreeItemInternal.ts | 93 +- Source/commands/api/apiCache.ts | 82 +- Source/commands/api/findTreeItem.ts | 355 +- Source/commands/api/pickTreeItem.ts | 220 +- Source/commands/api/revealTreeItem.ts | 29 +- .../DatabaseAccountDeleteStep.ts | 14 +- .../IDeleteWizardContext.ts | 25 +- .../deleteCosmosDBAccount.ts | 69 +- .../deleteDatabaseAccount.ts | 60 +- Source/commands/importDocuments.ts | 328 +- Source/docdb/docDBConnectionStrings.ts | 78 +- Source/docdb/getCosmosClient.ts | 35 +- Source/docdb/registerDocDBCommands.ts | 238 +- Source/docdb/tree/DocDBAccountTreeItem.ts | 56 +- Source/docdb/tree/DocDBAccountTreeItemBase.ts | 188 +- Source/docdb/tree/DocDBCollectionTreeItem.ts | 187 +- Source/docdb/tree/DocDBDatabaseTreeItem.ts | 31 +- .../docdb/tree/DocDBDatabaseTreeItemBase.ts | 329 +- Source/docdb/tree/DocDBDocumentTreeItem.ts | 286 +- Source/docdb/tree/DocDBDocumentsTreeItem.ts | 269 +- .../tree/DocDBStoredProcedureTreeItem.ts | 134 +- .../tree/DocDBStoredProceduresTreeItem.ts | 216 +- Source/docdb/tree/DocDBTreeItemBase.ts | 79 +- Source/docdb/tree/DocDBUtils.ts | 2 +- Source/docdb/tree/IDocDBTreeRoot.ts | 9 +- Source/graph/gremlinEndpoints.ts | 74 +- Source/graph/registerGraphCommands.ts | 125 +- Source/graph/tree/GraphAccountTreeItem.ts | 87 +- Source/graph/tree/GraphCollectionTreeItem.ts | 181 +- Source/graph/tree/GraphDatabaseTreeItem.ts | 109 +- Source/graph/tree/GraphTreeItem.ts | 105 +- Source/mongo/MongoCommand.ts | 26 +- Source/mongo/MongoScrapbook.ts | 1135 ++++--- Source/mongo/MongoShell.ts | 353 +- Source/mongo/connectToMongoClient.ts | 87 +- Source/mongo/errorListeners.ts | 98 +- Source/mongo/grammar/mongoLexer.ts | 535 +-- Source/mongo/grammar/mongoListener.ts | 36 +- Source/mongo/grammar/mongoParser.ts | 2994 +++++++++-------- Source/mongo/grammar/mongoVisitor.ts | 32 +- Source/mongo/grammar/visitors.ts | 157 +- Source/mongo/languageClient.ts | 120 +- Source/mongo/languageServer.ts | 4 +- Source/mongo/mongoConnectionStrings.ts | 158 +- Source/mongo/registerMongoCommands.ts | 500 ++- Source/mongo/services/IConnectionParams.ts | 6 +- .../mongo/services/MongoCodeLensProvider.ts | 130 +- .../mongo/services/completionItemProvider.ts | 1015 +++--- Source/mongo/services/languageService.ts | 193 +- Source/mongo/services/mongoScript.ts | 195 +- Source/mongo/services/schemaService.ts | 1336 ++++---- Source/mongo/setConnectedNode.ts | 10 +- Source/mongo/tree/IMongoTreeRoot.ts | 3 +- Source/mongo/tree/MongoAccountTreeItem.ts | 307 +- Source/mongo/tree/MongoCollectionTreeItem.ts | 753 +++-- Source/mongo/tree/MongoDatabaseTreeItem.ts | 611 ++-- Source/mongo/tree/MongoDocumentTreeItem.ts | 182 +- .../abstract/AbstractPostgresClient.ts | 30 +- Source/postgres/abstract/models.ts | 73 +- .../postgres/commands/checkAuthentication.ts | 56 +- .../commands/configurePostgresFirewall.ts | 128 +- .../commands/connectPostgresDatabase.ts | 70 +- .../postgres/commands/copyConnectionString.ts | 76 +- .../commands/createPostgresDatabase.ts | 49 +- .../commands/deletePostgresDatabase.ts | 61 +- .../commands/deletePostgresFunction.ts | 57 +- .../postgres/commands/deletePostgresServer.ts | 37 +- .../commands/deletePostgresStoredProcedure.ts | 60 +- .../postgres/commands/deletePostgresTable.ts | 56 +- .../commands/enterPostgresCredentials.ts | 153 +- .../executePostgresQueryInDocument.ts | 127 +- .../postgres/commands/openPostgresFunction.ts | 23 +- .../commands/openPostgresStoredProcedure.ts | 24 +- .../commands/registerPostgresCommands.ts | 166 +- .../commands/setPostgresCredentials.ts | 44 +- Source/postgres/getClientConfig.ts | 187 +- .../postgres/getPostgresProcedureQueryRows.ts | 61 +- Source/postgres/getTables.ts | 34 +- Source/postgres/postgresConnectionStrings.ts | 123 +- Source/postgres/postgresConstants.ts | 6 +- Source/postgres/runPostgresQuery.ts | 21 +- .../services/PostgresCodeLensProvider.ts | 122 +- Source/postgres/showPostgresQuery.ts | 16 +- Source/postgres/tree/ClientConfigFactory.ts | 171 +- .../postgres/tree/PostgresColumnTreeItem.ts | 41 +- .../postgres/tree/PostgresDatabaseTreeItem.ts | 252 +- .../postgres/tree/PostgresFunctionTreeItem.ts | 70 +- .../tree/PostgresFunctionsTreeItem.ts | 70 +- .../tree/PostgresResourcesTreeItemBase.ts | 26 +- .../postgres/tree/PostgresServerTreeItem.ts | 611 ++-- .../tree/PostgresStoredProcedureTreeItem.ts | 68 +- .../tree/PostgresStoredProceduresTreeItem.ts | 74 +- Source/postgres/tree/PostgresTableTreeItem.ts | 92 +- .../postgres/tree/PostgresTablesTreeItem.ts | 81 +- Source/resolver/AppResolver.ts | 149 +- Source/resolver/DatabaseWorkspaceProvider.ts | 48 +- .../ResolvedDatabaseAccountResource.ts | 117 +- .../resolver/ResolvedDocDBAccountResource.ts | 63 +- .../resolver/ResolvedMongoAccountResource.ts | 22 +- .../ResolvedPostgresServerResource.ts | 79 +- Source/table/tree/TableAccountTreeItem.ts | 50 +- Source/tree/AttachedAccountsTreeItem.ts | 973 +++--- .../tree/AzureAccountTreeItemWithAttached.ts | 65 +- Source/tree/AzureDBAPIStep.ts | 159 +- .../CosmosDBAccountCapacityStep.ts | 73 +- .../CosmosDBAccountCreateStep.ts | 130 +- .../CosmosDBAccountNameStep.ts | 85 +- .../ICosmosDBWizardContext.ts | 24 +- Source/tree/IAzureDBWizardContext.ts | 10 +- Source/tree/SubscriptionTreeItem.ts | 460 ++- Source/utils/InteractiveChildProcess.ts | 336 +- Source/utils/activityUtils.ts | 13 +- Source/utils/array.ts | 18 +- Source/utils/azureClients.ts | 39 +- Source/utils/azureUtils.ts | 12 +- Source/utils/cp.ts | 17 +- Source/utils/getIp.ts | 106 +- Source/utils/getSecretStorageKey.ts | 2 +- Source/utils/improveError.ts | 14 +- Source/utils/localize.ts | 2 +- Source/utils/nonNull.ts | 49 +- Source/utils/openUrl.ts | 8 +- Source/utils/randomUtils.ts | 17 +- Source/utils/settingUtils.ts | 98 +- Source/utils/timeout.ts | 70 +- Source/utils/vscodeUtils.ts | 180 +- Source/utils/workspacUtils.ts | 21 +- Source/utils/wrapError.ts | 26 +- .../icons/theme-agnostic/CosmosDBAccount.svg | 57 +- .../icons/theme-agnostic/PostgresServer.svg | 28 +- 131 files changed, 13139 insertions(+), 9186 deletions(-) diff --git a/Source/commands/api/DatabaseAccountTreeItemInternal.ts b/Source/commands/api/DatabaseAccountTreeItemInternal.ts index 89a8c1164..6a5cebe8a 100644 --- a/Source/commands/api/DatabaseAccountTreeItemInternal.ts +++ b/Source/commands/api/DatabaseAccountTreeItemInternal.ts @@ -3,104 +3,146 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { API } from '../../AzureDBExperiences'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api'; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { API } from "../../AzureDBExperiences"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { ParsedPostgresConnectionString } from "../../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { nonNullProp } from "../../utils/nonNull"; +import { DatabaseAccountTreeItem } from "../../vscode-cosmosdb.api"; -export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem { - protected _parsedCS: ParsedConnectionString; - private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined; +export class DatabaseAccountTreeItemInternal + implements DatabaseAccountTreeItem +{ + protected _parsedCS: ParsedConnectionString; + private _accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + | undefined; - constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) { - this._parsedCS = parsedCS; - this._accountNode = accountNode; - } + constructor( + parsedCS: ParsedConnectionString, + accountNode?: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + ) { + this._parsedCS = parsedCS; + this._accountNode = accountNode; + } - public get connectionString(): string { - return this._parsedCS.connectionString; - } + public get connectionString(): string { + return this._parsedCS.connectionString; + } - public get hostName(): string { - return this._parsedCS.hostName; - } + public get hostName(): string { + return this._parsedCS.hostName; + } - public get port(): string { - return this._parsedCS.port; - } + public get port(): string { + return this._parsedCS.port; + } - public get azureData(): { accountName: string, accountId: string } | undefined { - if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) { - if (this._accountNode?.databaseAccount) { - return { - accountName: nonNullProp(this._accountNode.databaseAccount, 'name'), - accountId: this._accountNode.fullId - }; - } - } else if (this._accountNode instanceof PostgresServerTreeItem) { - if (this._accountNode.azureName) { - return { - accountName: this._accountNode.azureName, - accountId: this._accountNode.fullId - }; - } - } - return undefined; - } + public get azureData(): + | { accountName: string; accountId: string } + | undefined { + if ( + this._accountNode instanceof MongoAccountTreeItem || + this._accountNode instanceof DocDBAccountTreeItemBase + ) { + if (this._accountNode?.databaseAccount) { + return { + accountName: nonNullProp( + this._accountNode.databaseAccount, + "name" + ), + accountId: this._accountNode.fullId, + }; + } + } else if (this._accountNode instanceof PostgresServerTreeItem) { + if (this._accountNode.azureName) { + return { + accountName: this._accountNode.azureName, + accountId: this._accountNode.fullId, + }; + } + } + return undefined; + } - public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined { - if (this._accountNode instanceof DocDBAccountTreeItemBase) { - return { - documentEndpoint: this._accountNode.root.endpoint, - masterKey: this._accountNode.root.masterKey - }; - } else { - return undefined; - } - } + public get docDBData(): + | { masterKey: string; documentEndpoint: string } + | undefined { + if (this._accountNode instanceof DocDBAccountTreeItemBase) { + return { + documentEndpoint: this._accountNode.root.endpoint, + masterKey: this._accountNode.root.masterKey, + }; + } else { + return undefined; + } + } - public get postgresData(): { username: string | undefined; password: string | undefined } | undefined { - if (this._parsedCS instanceof ParsedPostgresConnectionString) { - const connectionString = this._parsedCS; - return { - username: connectionString.username, - password: connectionString.password - }; - } else { - return undefined; - } - } + public get postgresData(): + | { username: string | undefined; password: string | undefined } + | undefined { + if (this._parsedCS instanceof ParsedPostgresConnectionString) { + const connectionString = this._parsedCS; + return { + username: connectionString.username, + password: connectionString.password, + }; + } else { + return undefined; + } + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.dbAccount.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - await ext.rgApi.appResourceTreeView.reveal(await this.getAccountNode(context)); - }); - } + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling( + "api.dbAccount.reveal", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + await ext.rgApi.appResourceTreeView.reveal( + await this.getAccountNode(context) + ); + } + ); + } - protected async getAccountNode(context: IActionContext): Promise { - // If this._accountNode is undefined, attach a new node based on connection string - if (!this._accountNode) { + protected async getAccountNode( + context: IActionContext + ): Promise< + MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem + > { + // If this._accountNode is undefined, attach a new node based on connection string + if (!this._accountNode) { + let apiType: API; + if (this._parsedCS instanceof ParsedMongoConnectionString) { + apiType = API.MongoDB; + } else if ( + this._parsedCS instanceof ParsedPostgresConnectionString + ) { + apiType = API.PostgresSingle; + } else { + apiType = API.Core; + } + this._accountNode = + await ext.attachedAccountsNode.attachConnectionString( + context, + this.connectionString, + apiType + ); + } - let apiType: API; - if (this._parsedCS instanceof ParsedMongoConnectionString) { - apiType = API.MongoDB; - } else if (this._parsedCS instanceof ParsedPostgresConnectionString) { - apiType = API.PostgresSingle; - } else { - apiType = API.Core; - } - this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType); - } - - return this._accountNode; - } + return this._accountNode; + } } diff --git a/Source/commands/api/DatabaseTreeItemInternal.ts b/Source/commands/api/DatabaseTreeItemInternal.ts index 9d6b0d140..8fa8389b2 100644 --- a/Source/commands/api/DatabaseTreeItemInternal.ts +++ b/Source/commands/api/DatabaseTreeItemInternal.ts @@ -3,40 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { DatabaseTreeItem } from '../../vscode-cosmosdb.api'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { DatabaseTreeItem } from "../../vscode-cosmosdb.api"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; -export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem { - public databaseName: string; - private _dbNode: AzExtTreeItem | undefined; +export class DatabaseTreeItemInternal + extends DatabaseAccountTreeItemInternal + implements DatabaseTreeItem +{ + public databaseName: string; + private _dbNode: AzExtTreeItem | undefined; - constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) { - super(parsedCS, accountNode); - this.databaseName = databaseName; - this._dbNode = dbNode; - } + constructor( + parsedCS: ParsedConnectionString, + databaseName: string, + accountNode?: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem, + dbNode?: + | MongoDatabaseTreeItem + | DocDBDatabaseTreeItemBase + | PostgresDatabaseTreeItem + ) { + super(parsedCS, accountNode); + this.databaseName = databaseName; + this._dbNode = dbNode; + } - public async reveal(): Promise { - await callWithTelemetryAndErrorHandling('api.db.reveal', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + public async reveal(): Promise { + await callWithTelemetryAndErrorHandling( + "api.db.reveal", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; - const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context); - if (!this._dbNode) { - const databaseId = `${accountNode.fullId}/${this.databaseName}`; - this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context); - } + const accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem = + await this.getAccountNode(context); + if (!this._dbNode) { + const databaseId = `${accountNode.fullId}/${this.databaseName}`; + this._dbNode = + await ext.rgApi.workspaceResourceTree.findTreeItem( + databaseId, + context + ); + } - await ext.rgApi.workspaceResourceTreeView.reveal(this._dbNode || accountNode); - }); - } + await ext.rgApi.workspaceResourceTreeView.reveal( + this._dbNode || accountNode + ); + } + ); + } } diff --git a/Source/commands/api/apiCache.ts b/Source/commands/api/apiCache.ts index 30da342aa..9020478fd 100644 --- a/Source/commands/api/apiCache.ts +++ b/Source/commands/api/apiCache.ts @@ -3,44 +3,68 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api'; +import { ParsedDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { ParsedMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { + ParsedPostgresConnectionString, + parsePostgresConnectionString, +} from "../../postgres/postgresConnectionStrings"; +import { + DatabaseAccountTreeItem, + DatabaseTreeItem, +} from "../../vscode-cosmosdb.api"; /** * This cache is used to speed up api calls from other extensions to the Cosmos DB extension * For now, it only helps on a per-session basis */ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const sessionCache: Map = new Map(); +const sessionCache: Map = + new Map(); -export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void { - sessionCache.set(parsedCS.fullId, treeItem); +export function cacheTreeItem( + parsedCS: ParsedConnectionString, + treeItem: DatabaseAccountTreeItem | DatabaseTreeItem +): void { + sessionCache.set(parsedCS.fullId, treeItem); } -export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { - return sessionCache.get(parsedCS.fullId); +export function tryGetTreeItemFromCache( + parsedCS: ParsedConnectionString +): DatabaseAccountTreeItem | DatabaseTreeItem | undefined { + return sessionCache.get(parsedCS.fullId); } -export function removeTreeItemFromCache(expected: ParsedConnectionString): void { - if (!expected.databaseName) { - // If parsedCS represents an account, remove the account and any databases that match that account - for (const [key, value] of sessionCache.entries()) { - let actual: ParsedConnectionString | undefined; - if (expected instanceof ParsedPostgresConnectionString) { - actual = parsePostgresConnectionString(value.connectionString); - } else if (expected instanceof ParsedMongoConnectionString) { - actual = new ParsedMongoConnectionString(value.connectionString, value.hostName, value.port, undefined); - } else { - actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined); - } - if (actual && (actual.accountId === expected.accountId)) { - sessionCache.delete(key); - } - } - } else { - sessionCache.delete(expected.fullId); - } +export function removeTreeItemFromCache( + expected: ParsedConnectionString +): void { + if (!expected.databaseName) { + // If parsedCS represents an account, remove the account and any databases that match that account + for (const [key, value] of sessionCache.entries()) { + let actual: ParsedConnectionString | undefined; + if (expected instanceof ParsedPostgresConnectionString) { + actual = parsePostgresConnectionString(value.connectionString); + } else if (expected instanceof ParsedMongoConnectionString) { + actual = new ParsedMongoConnectionString( + value.connectionString, + value.hostName, + value.port, + undefined + ); + } else { + actual = new ParsedDocDBConnectionString( + value.connectionString, + value.hostName, + value.port, + undefined + ); + } + if (actual && actual.accountId === expected.accountId) { + sessionCache.delete(key); + } + } + } else { + sessionCache.delete(expected.fullId); + } } diff --git a/Source/commands/api/findTreeItem.ts b/Source/commands/api/findTreeItem.ts index 088413e52..d7e0f0d01 100644 --- a/Source/commands/api/findTreeItem.ts +++ b/Source/commands/api/findTreeItem.ts @@ -3,144 +3,223 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem'; -import { nonNullProp } from '../../utils/nonNull'; -import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; - -export async function findTreeItem(query: TreeItemQuery): Promise { - return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; - - let parsedCS: ParsedConnectionString; - if (query.postgresData) { - const postgresData = query.postgresData; - const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName); - parsedCS = parsePostgresConnectionString(connectionString); - } else { - const connectionString = nonNullProp(query, 'connectionString'); - if (/^mongodb[^:]*:\/\//i.test(connectionString)) { - parsedCS = await parseMongoConnectionString(connectionString); - } else if (/^postgres:\/\//i.test(connectionString)) { - parsedCS = parsePostgresConnectionString(connectionString); - } else { - parsedCS = parseDocDBConnectionString(connectionString); - } - } - - const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account - - // 1. Get result from cache if possible - let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = tryGetTreeItemFromCache(parsedCS); - - // 2. Search attached accounts (do this before subscriptions because it's faster) - if (!result) { - const attachedDbAccounts = await ext.attachedAccountsNode.getCachedChildren(context); - result = await searchDbAccounts(attachedDbAccounts, parsedCS, context, maxTime); - } - - // 3. Search subscriptions - if (!result) { - const rootNodes = await ext.rgApi.appResourceTree.getChildren(); - for (const rootNode of rootNodes) { - if (Date.now() > maxTime) { - break; - } - - if (rootNode instanceof SubscriptionTreeItem) { - const dbAccounts = await rootNode.getCachedChildren(context); - result = await searchDbAccounts(dbAccounts, parsedCS, context, maxTime); - if (result) { - break; - } - } - } - } - - // 4. If all else fails, just attach a new node - if (!result) { - if (parsedCS.databaseName) { - result = new DatabaseTreeItemInternal(parsedCS, parsedCS.databaseName); - } else { - result = new DatabaseAccountTreeItemInternal(parsedCS); - } - } - - cacheTreeItem(parsedCS, result); - - return result; - }); +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { + createPostgresConnectionString, + parsePostgresConnectionString, +} from "../../postgres/postgresConnectionStrings"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { SubscriptionTreeItem } from "../../tree/SubscriptionTreeItem"; +import { nonNullProp } from "../../utils/nonNull"; +import { + DatabaseAccountTreeItem, + DatabaseTreeItem, + TreeItemQuery, +} from "../../vscode-cosmosdb.api"; +import { cacheTreeItem, tryGetTreeItemFromCache } from "./apiCache"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; + +export async function findTreeItem( + query: TreeItemQuery +): Promise { + return await callWithTelemetryAndErrorHandling( + "api.findTreeItem", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; + + let parsedCS: ParsedConnectionString; + if (query.postgresData) { + const postgresData = query.postgresData; + const connectionString: string = createPostgresConnectionString( + postgresData.hostName, + postgresData.port, + postgresData.username, + postgresData.password, + postgresData.databaseName + ); + parsedCS = parsePostgresConnectionString(connectionString); + } else { + const connectionString = nonNullProp(query, "connectionString"); + if (/^mongodb[^:]*:\/\//i.test(connectionString)) { + parsedCS = + await parseMongoConnectionString(connectionString); + } else if (/^postgres:\/\//i.test(connectionString)) { + parsedCS = parsePostgresConnectionString(connectionString); + } else { + parsedCS = parseDocDBConnectionString(connectionString); + } + } + + const maxTime = Date.now() + 10 * 1000; // Give up searching subscriptions after 10 seconds and just attach the account + + // 1. Get result from cache if possible + let result: DatabaseAccountTreeItem | DatabaseTreeItem | undefined = + tryGetTreeItemFromCache(parsedCS); + + // 2. Search attached accounts (do this before subscriptions because it's faster) + if (!result) { + const attachedDbAccounts = + await ext.attachedAccountsNode.getCachedChildren(context); + result = await searchDbAccounts( + attachedDbAccounts, + parsedCS, + context, + maxTime + ); + } + + // 3. Search subscriptions + if (!result) { + const rootNodes = await ext.rgApi.appResourceTree.getChildren(); + for (const rootNode of rootNodes) { + if (Date.now() > maxTime) { + break; + } + + if (rootNode instanceof SubscriptionTreeItem) { + const dbAccounts = + await rootNode.getCachedChildren(context); + result = await searchDbAccounts( + dbAccounts, + parsedCS, + context, + maxTime + ); + if (result) { + break; + } + } + } + } + + // 4. If all else fails, just attach a new node + if (!result) { + if (parsedCS.databaseName) { + result = new DatabaseTreeItemInternal( + parsedCS, + parsedCS.databaseName + ); + } else { + result = new DatabaseAccountTreeItemInternal(parsedCS); + } + } + + cacheTreeItem(parsedCS, result); + + return result; + } + ); } -async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise { - try { - for (const dbAccount of dbAccounts) { - if (Date.now() > maxTime) { - return undefined; - } - - let actual: ParsedConnectionString; - if (dbAccount instanceof MongoAccountTreeItem) { - actual = await parseMongoConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof DocDBAccountTreeItemBase) { - actual = parseDocDBConnectionString(dbAccount.connectionString); - } else if (dbAccount instanceof PostgresServerTreeItem) { - actual = dbAccount.partialConnectionString; - } else { - return undefined; - } - - if (expected.accountId === actual.accountId) { - if (expected.databaseName) { - const dbs = await dbAccount.getCachedChildren(context); - for (const db of dbs) { - if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db); - } - if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db); - } - } - - // We found the right account - just not the db. In this case we can still 'reveal' the account - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount); - } else { - return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount); - } - - } - - if (dbAccount instanceof PostgresServerTreeItem) { - const fullConnectionString = await dbAccount.getFullConnectionString(); - return new DatabaseAccountTreeItemInternal(fullConnectionString, dbAccount); - } else { - return new DatabaseAccountTreeItemInternal(expected, dbAccount); - } - - } - } - } catch (error) { - // Swallow all errors to avoid blocking the db account search - // https://github.com/microsoft/vscode-cosmosdb/issues/966 - } - - return undefined; +async function searchDbAccounts( + dbAccounts: AzExtTreeItem[], + expected: ParsedConnectionString, + context: IActionContext, + maxTime: number +): Promise { + try { + for (const dbAccount of dbAccounts) { + if (Date.now() > maxTime) { + return undefined; + } + + let actual: ParsedConnectionString; + if (dbAccount instanceof MongoAccountTreeItem) { + actual = await parseMongoConnectionString( + dbAccount.connectionString + ); + } else if (dbAccount instanceof DocDBAccountTreeItemBase) { + actual = parseDocDBConnectionString(dbAccount.connectionString); + } else if (dbAccount instanceof PostgresServerTreeItem) { + actual = dbAccount.partialConnectionString; + } else { + return undefined; + } + + if (expected.accountId === actual.accountId) { + if (expected.databaseName) { + const dbs = await dbAccount.getCachedChildren(context); + for (const db of dbs) { + if ( + (db instanceof MongoDatabaseTreeItem || + db instanceof DocDBDatabaseTreeItemBase) && + expected.databaseName === db.databaseName + ) { + return new DatabaseTreeItemInternal( + expected, + expected.databaseName, + dbAccount, + db + ); + } + if ( + db instanceof PostgresDatabaseTreeItem && + dbAccount instanceof PostgresServerTreeItem && + expected.databaseName === db.databaseName + ) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal( + fullConnectionString, + expected.databaseName, + dbAccount, + db + ); + } + } + + // We found the right account - just not the db. In this case we can still 'reveal' the account + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseTreeItemInternal( + fullConnectionString, + expected.databaseName, + dbAccount + ); + } else { + return new DatabaseTreeItemInternal( + expected, + expected.databaseName, + dbAccount + ); + } + } + + if (dbAccount instanceof PostgresServerTreeItem) { + const fullConnectionString = + await dbAccount.getFullConnectionString(); + return new DatabaseAccountTreeItemInternal( + fullConnectionString, + dbAccount + ); + } else { + return new DatabaseAccountTreeItemInternal( + expected, + dbAccount + ); + } + } + } + } catch (error) { + // Swallow all errors to avoid blocking the db account search + // https://github.com/microsoft/vscode-cosmosdb/issues/966 + } + + return undefined; } diff --git a/Source/commands/api/pickTreeItem.ts b/Source/commands/api/pickTreeItem.ts index dc84ce55a..f67ab039d 100644 --- a/Source/commands/api/pickTreeItem.ts +++ b/Source/commands/api/pickTreeItem.ts @@ -3,98 +3,146 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils'; -import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi'; -import { databaseAccountType } from '../../constants'; -import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBDatabaseTreeItem } from '../../docdb/tree/DocDBDatabaseTreeItem'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { ext } from '../../extensionVariables'; -import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem'; -import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem'; -import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem'; -import { localize } from '../../utils/localize'; -import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api'; -import { cacheTreeItem } from './apiCache'; -import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal'; -import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal'; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { PickAppResourceOptions } from "@microsoft/vscode-azext-utils/hostapi"; +import { databaseAccountType } from "../../constants"; +import { parseDocDBConnectionString } from "../../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBDatabaseTreeItem } from "../../docdb/tree/DocDBDatabaseTreeItem"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { ext } from "../../extensionVariables"; +import { GraphDatabaseTreeItem } from "../../graph/tree/GraphDatabaseTreeItem"; +import { parseMongoConnectionString } from "../../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../../mongo/tree/MongoAccountTreeItem"; +import { MongoDatabaseTreeItem } from "../../mongo/tree/MongoDatabaseTreeItem"; +import { ParsedConnectionString } from "../../ParsedConnectionString"; +import { PostgresDatabaseTreeItem } from "../../postgres/tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../../postgres/tree/PostgresServerTreeItem"; +import { localize } from "../../utils/localize"; +import { + AzureDatabasesApiType, + DatabaseAccountTreeItem, + DatabaseTreeItem, + PickTreeItemOptions, +} from "../../vscode-cosmosdb.api"; +import { cacheTreeItem } from "./apiCache"; +import { DatabaseAccountTreeItemInternal } from "./DatabaseAccountTreeItemInternal"; +import { DatabaseTreeItemInternal } from "./DatabaseTreeItemInternal"; -const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue]; +const databaseContextValues = [ + MongoDatabaseTreeItem.contextValue, + DocDBDatabaseTreeItem.contextValue, + GraphDatabaseTreeItem.contextValue, + PostgresDatabaseTreeItem.contextValue, +]; function getDatabaseContextValue(apiType: AzureDatabasesApiType): string { - switch (apiType) { - case 'Mongo': - return MongoDatabaseTreeItem.contextValue; - case 'SQL': - return DocDBDatabaseTreeItem.contextValue; - case 'Graph': - return GraphDatabaseTreeItem.contextValue; - case 'Postgres': - return PostgresDatabaseTreeItem.contextValue; - default: - throw new RangeError(`Unsupported api type "${apiType}".`); - } + switch (apiType) { + case "Mongo": + return MongoDatabaseTreeItem.contextValue; + case "SQL": + return DocDBDatabaseTreeItem.contextValue; + case "Graph": + return GraphDatabaseTreeItem.contextValue; + case "Postgres": + return PostgresDatabaseTreeItem.contextValue; + default: + throw new RangeError(`Unsupported api type "${apiType}".`); + } } +export async function pickTreeItem( + pickTreeOptions: PickTreeItemOptions +): Promise { + return await callWithTelemetryAndErrorHandling( + "api.pickTreeItem", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.errorHandling.rethrow = true; -export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise { - return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.errorHandling.rethrow = true; + const options: PickAppResourceOptions = {}; + switch (pickTreeOptions.resourceType) { + case "Database": + options.filter = { type: databaseAccountType }; + options.expectedChildContextValue = pickTreeOptions.apiType + ? pickTreeOptions.apiType.map(getDatabaseContextValue) + : databaseContextValues; + break; + case "DatabaseAccount": + options.filter = { type: databaseAccountType }; + break; + default: + throw new RangeError( + `Unsupported resource type "${pickTreeOptions.resourceType}".` + ); + } - const options: PickAppResourceOptions = {}; - switch (pickTreeOptions.resourceType) { - case 'Database': - options.filter = { type: databaseAccountType }; - options.expectedChildContextValue = pickTreeOptions.apiType ? - pickTreeOptions.apiType.map(getDatabaseContextValue) : - databaseContextValues; - break; - case 'DatabaseAccount': - options.filter = { type: databaseAccountType }; - break; - default: - throw new RangeError(`Unsupported resource type "${pickTreeOptions.resourceType}".`); - } + const pickedItem = await ext.rgApi.pickAppResource( + context, + options + ); - const pickedItem = await ext.rgApi.pickAppResource(context, options); + let parsedCS: ParsedConnectionString; + let accountNode: + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem; + let databaseNode: + | MongoDatabaseTreeItem + | DocDBDatabaseTreeItemBase + | PostgresDatabaseTreeItem + | undefined; + if (pickedItem instanceof MongoAccountTreeItem) { + parsedCS = await parseMongoConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem; + } else if (pickedItem instanceof DocDBAccountTreeItemBase) { + parsedCS = parseDocDBConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem; + } else if (pickedItem instanceof PostgresServerTreeItem) { + parsedCS = await pickedItem.getFullConnectionString(); + accountNode = pickedItem; + } else if (pickedItem instanceof MongoDatabaseTreeItem) { + parsedCS = await parseMongoConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { + parsedCS = parseDocDBConnectionString( + pickedItem.connectionString + ); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else if (pickedItem instanceof PostgresDatabaseTreeItem) { + parsedCS = await pickedItem.parent.getFullConnectionString(); + accountNode = pickedItem.parent; + databaseNode = pickedItem; + } else { + throw new RangeError( + localize( + "invalidItem", + 'Invalid item "{0}".', + pickedItem.constructor.name + ) + ); + } - let parsedCS: ParsedConnectionString; - let accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem; - let databaseNode: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem | undefined; - if (pickedItem instanceof MongoAccountTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof DocDBAccountTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem; - } else if (pickedItem instanceof PostgresServerTreeItem) { - parsedCS = await pickedItem.getFullConnectionString(); - accountNode = pickedItem; - } else if (pickedItem instanceof MongoDatabaseTreeItem) { - parsedCS = await parseMongoConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof DocDBDatabaseTreeItemBase) { - parsedCS = parseDocDBConnectionString(pickedItem.connectionString); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else if (pickedItem instanceof PostgresDatabaseTreeItem) { - parsedCS = await pickedItem.parent.getFullConnectionString(); - accountNode = pickedItem.parent; - databaseNode = pickedItem; - } else { - throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name)); - } - - const result = databaseNode ? - new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) : - new DatabaseAccountTreeItemInternal(parsedCS, accountNode); - cacheTreeItem(parsedCS, result); - return result; - }); + const result = databaseNode + ? new DatabaseTreeItemInternal( + parsedCS, + databaseNode.databaseName, + accountNode, + databaseNode + ) + : new DatabaseAccountTreeItemInternal(parsedCS, accountNode); + cacheTreeItem(parsedCS, result); + return result; + } + ); } diff --git a/Source/commands/api/revealTreeItem.ts b/Source/commands/api/revealTreeItem.ts index d13589351..185ff340c 100644 --- a/Source/commands/api/revealTreeItem.ts +++ b/Source/commands/api/revealTreeItem.ts @@ -3,14 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { ext } from "../../extensionVariables"; export async function revealTreeItem(resourceId: string): Promise { - return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => { - const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true }); - if (node) { - await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true }); - } - }); + return await callWithTelemetryAndErrorHandling( + "api.revealTreeItem", + async (context: IActionContext) => { + const node: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem(resourceId, { + ...context, + loadAll: true, + }); + if (node) { + await ext.rgApi.appResourceTreeView.reveal(node, { + select: true, + focus: true, + expand: true, + }); + } + } + ); } diff --git a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts index 1ef9ca645..d409dcc0a 100644 --- a/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts +++ b/Source/commands/deleteDatabaseAccount/DatabaseAccountDeleteStep.ts @@ -7,13 +7,13 @@ import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IDeleteWizardContext): Promise { - await context.node.deleteTreeItem(context); - } + public async execute(context: IDeleteWizardContext): Promise { + await context.node.deleteTreeItem(context); + } - public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { - return true; - } + public shouldExecute(_wizardContext: IDeleteWizardContext): boolean { + return true; + } } diff --git a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts index 762beb96e..e20bafa90 100644 --- a/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts +++ b/Source/commands/deleteDatabaseAccount/IDeleteWizardContext.ts @@ -1,13 +1,20 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + ExecuteActivityContext, + IActionContext, + ISubscriptionContext, +} from "@microsoft/vscode-azext-utils"; -export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext { - node: AzExtTreeItem; - deletePostgres: boolean; - resourceGroupToDelete?: string; - subscription: ISubscriptionContext; +export interface IDeleteWizardContext + extends IActionContext, + ExecuteActivityContext { + node: AzExtTreeItem; + deletePostgres: boolean; + resourceGroupToDelete?: string; + subscription: ISubscriptionContext; } diff --git a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts index a90956b30..b862cb33e 100644 --- a/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteCosmosDBAccount.ts @@ -3,30 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { getDatabaseAccountNameFromId } from '../../utils/azureUtils'; -import { localize } from '../../utils/localize'; -import { IDeleteWizardContext } from './IDeleteWizardContext'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; +import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { ext } from "../../extensionVariables"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { getDatabaseAccountNameFromId } from "../../utils/azureUtils"; +import { localize } from "../../utils/localize"; +import { IDeleteWizardContext } from "./IDeleteWizardContext"; -export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise { - const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]); - const resourceGroup: string = getResourceGroupFromId(node.fullId); - const accountName: string = getDatabaseAccountNameFromId(node.fullId); - const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName); - if (!context.suppressNotification) { - const deletingMessage: string = `Deleting account "${accountName}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await deletePromise; - const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } else { - await deletePromise; - } +export async function deleteCosmosDBAccount( + context: IDeleteWizardContext, + node: AzExtTreeItem +): Promise { + const client: CosmosDBManagementClient = await createCosmosDBClient([ + context, + node.subscription, + ]); + const resourceGroup: string = getResourceGroupFromId(node.fullId); + const accountName: string = getDatabaseAccountNameFromId(node.fullId); + const deletePromise = client.databaseAccounts.beginDeleteAndWait( + resourceGroup, + accountName + ); + if (!context.suppressNotification) { + const deletingMessage: string = `Deleting account "${accountName}"...`; + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: deletingMessage, + }, + async () => { + await deletePromise; + const deleteMessage: string = localize( + "deleteAccountMsg", + `Successfully deleted account "{0}".`, + accountName + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + } + ); + } else { + await deletePromise; + } } diff --git a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts index 4792710d4..ac6857848 100644 --- a/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts +++ b/Source/commands/deleteDatabaseAccount/deleteDatabaseAccount.ts @@ -3,35 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + AzureWizard, + DeleteConfirmationStep, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { createActivityContext } from "../../utils/activityUtils"; import { localize } from "../../utils/localize"; import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep"; import { IDeleteWizardContext } from "./IDeleteWizardContext"; +export async function deleteDatabaseAccount( + context: IActionContext, + node: AzExtTreeItem, + isPostgres: boolean = false +): Promise { + const wizardContext: IDeleteWizardContext = Object.assign(context, { + node, + deletePostgres: isPostgres, + subscription: node.subscription, + ...(await createActivityContext()), + }); -export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise { - const wizardContext: IDeleteWizardContext = Object.assign(context, { - node, - deletePostgres: isPostgres, - subscription: node.subscription, - ...(await createActivityContext()) - }); + const title = wizardContext.deletePostgres + ? localize("deletePoSer", 'Delete Postgres Server "{0}"', node.label) + : localize("deleteDbAcc", 'Delete Database Account "{0}"', node.label); - const title = wizardContext.deletePostgres ? - localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) : - localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label) + const confirmationMessage = wizardContext.deletePostgres + ? localize( + "deleteAccountConfirm", + 'Are you sure you want to delete server "{0}" and its contents?', + node.label + ) + : localize( + "deleteAccountConfirm", + 'Are you sure you want to delete account "{0}" and its contents?', + node.label + ); - const confirmationMessage = wizardContext.deletePostgres ? - localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) : - localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label); + const wizard = new AzureWizard(wizardContext, { + title, + promptSteps: [new DeleteConfirmationStep(confirmationMessage)], + executeSteps: [new DatabaseAccountDeleteStep()], + }); - const wizard = new AzureWizard(wizardContext, { - title, - promptSteps: [new DeleteConfirmationStep(confirmationMessage)], - executeSteps: [new DatabaseAccountDeleteStep()] - }); - - await wizard.prompt(); - await wizard.execute(); + await wizard.prompt(); + await wizard.execute(); } diff --git a/Source/commands/importDocuments.ts b/Source/commands/importDocuments.ts index bd4c83e3f..305af31eb 100644 --- a/Source/commands/importDocuments.ts +++ b/Source/commands/importDocuments.ts @@ -3,161 +3,209 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from '@azure/cosmos'; -import { IActionContext, parseError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { cosmosMongoFilter, sqlFilter } from '../constants'; -import { DocDBCollectionTreeItem } from '../docdb/tree/DocDBCollectionTreeItem'; -import { ext } from '../extensionVariables'; -import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { getRootPath } from '../utils/workspacUtils'; +import { ItemDefinition } from "@azure/cosmos"; +import { IActionContext, parseError } from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import * as vscode from "vscode"; +import { cosmosMongoFilter, sqlFilter } from "../constants"; +import { DocDBCollectionTreeItem } from "../docdb/tree/DocDBCollectionTreeItem"; +import { ext } from "../extensionVariables"; +import { MongoCollectionTreeItem } from "../mongo/tree/MongoCollectionTreeItem"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { getRootPath } from "../utils/workspacUtils"; -export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise { - if (!uris) { - uris = await askForDocuments(context); - } - const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 - uris = uris.filter((uri) => { - if (uri.fsPath.toLocaleLowerCase().endsWith('.json')) { - return true; - } else { - ignoredUris.push(uri); - return false; - } - }); - if (ignoredUris.length) { - ext.outputChannel.appendLog(`Ignoring the following files which are not json:`); - ignoredUris.forEach(uri => ext.outputChannel.appendLine(`${uri.fsPath}`)); - ext.outputChannel.show(); - } - if (!collectionNode) { - collectionNode = await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter, - sqlFilter - ], - expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue] - }); - } - let result: string; - result = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: "Importing documents..." - }, - async (progress) => { - uris = nonNullValue(uris, 'uris'); - collectionNode = nonNullValue(collectionNode, 'collectionNode'); +export async function importDocuments( + context: IActionContext, + uris: vscode.Uri[] | undefined, + collectionNode: + | MongoCollectionTreeItem + | DocDBCollectionTreeItem + | undefined +): Promise { + if (!uris) { + uris = await askForDocuments(context); + } + const ignoredUris: vscode.Uri[] = []; //account for https://github.com/Microsoft/vscode/issues/59782 + uris = uris.filter((uri) => { + if (uri.fsPath.toLocaleLowerCase().endsWith(".json")) { + return true; + } else { + ignoredUris.push(uri); + return false; + } + }); + if (ignoredUris.length) { + ext.outputChannel.appendLog( + `Ignoring the following files which are not json:` + ); + ignoredUris.forEach((uri) => + ext.outputChannel.appendLine(`${uri.fsPath}`) + ); + ext.outputChannel.show(); + } + if (!collectionNode) { + collectionNode = await ext.rgApi.pickAppResource< + MongoCollectionTreeItem | DocDBCollectionTreeItem + >(context, { + filter: [cosmosMongoFilter, sqlFilter], + expectedChildContextValue: [ + MongoCollectionTreeItem.contextValue, + DocDBCollectionTreeItem.contextValue, + ], + }); + } + let result: string; + result = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Importing documents...", + }, + async (progress) => { + uris = nonNullValue(uris, "uris"); + collectionNode = nonNullValue(collectionNode, "collectionNode"); - progress.report({ increment: 20, message: "Parsing documents for errors" }); - const documents = await parseDocuments(uris); - progress.report({ increment: 30, message: "Parsed documents. Importing" }); - if (collectionNode instanceof MongoCollectionTreeItem) { - result = await insertDocumentsIntoMongo(collectionNode, documents); - } else { - result = await insertDocumentsIntoDocdb(collectionNode, documents, uris); - } - progress.report({ increment: 50, message: "Finished importing" }); - return result; - } - ); + progress.report({ + increment: 20, + message: "Parsing documents for errors", + }); + const documents = await parseDocuments(uris); + progress.report({ + increment: 30, + message: "Parsed documents. Importing", + }); + if (collectionNode instanceof MongoCollectionTreeItem) { + result = await insertDocumentsIntoMongo( + collectionNode, + documents + ); + } else { + result = await insertDocumentsIntoDocdb( + collectionNode, + documents, + uris + ); + } + progress.report({ increment: 50, message: "Finished importing" }); + return result; + } + ); - await collectionNode.refresh(context); - await vscode.window.showInformationMessage(result); + await collectionNode.refresh(context); + await vscode.window.showInformationMessage(result); } async function askForDocuments(context: IActionContext): Promise { - const openDialogOptions: vscode.OpenDialogOptions = { - canSelectMany: true, - openLabel: "Import", - filters: { - JSON: ["json"] - } - }; - const rootPath: string | undefined = getRootPath(); - if (rootPath) { - openDialogOptions.defaultUri = vscode.Uri.file(rootPath); - } - return await context.ui.showOpenDialog(openDialogOptions); + const openDialogOptions: vscode.OpenDialogOptions = { + canSelectMany: true, + openLabel: "Import", + filters: { + JSON: ["json"], + }, + }; + const rootPath: string | undefined = getRootPath(); + if (rootPath) { + openDialogOptions.defaultUri = vscode.Uri.file(rootPath); + } + return await context.ui.showOpenDialog(openDialogOptions); } // eslint-disable-next-line @typescript-eslint/no-explicit-any async function parseDocuments(uris: vscode.Uri[]): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let documents: any[] = []; - let errorFoundFlag: boolean = false; - for (const uri of uris) { - let parsed; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - parsed = await fse.readJSON(uri.fsPath); - } catch (e) { - if (!errorFoundFlag) { - errorFoundFlag = true; - ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these."); - ext.outputChannel.show(); - } - const err = parseError(e); - ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); - } - if (parsed) { - if (Array.isArray(parsed)) { - documents = documents.concat(parsed); - } else { - documents.push(parsed); - } - } - } - if (errorFoundFlag) { - throw new Error(`Errors found in some documents. Please see the output, fix these and try again.`); - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let documents: any[] = []; + let errorFoundFlag: boolean = false; + for (const uri of uris) { + let parsed; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + parsed = await fse.readJSON(uri.fsPath); + } catch (e) { + if (!errorFoundFlag) { + errorFoundFlag = true; + ext.outputChannel.appendLog( + "Errors found in documents listed below. Please fix these." + ); + ext.outputChannel.show(); + } + const err = parseError(e); + ext.outputChannel.appendLine(`${uri.path}:\n${err.message}`); + } + if (parsed) { + if (Array.isArray(parsed)) { + documents = documents.concat(parsed); + } else { + documents.push(parsed); + } + } + } + if (errorFoundFlag) { + throw new Error( + `Errors found in some documents. Please see the output, fix these and try again.` + ); + } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return documents; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return documents; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise { - const ids: string[] = []; - let i = 0; - const erroneousFiles: vscode.Uri[] = []; - for (i = 0; i < documents.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const document: ItemDefinition = documents[i]; - if (!collectionNode.documentsTreeItem.documentHasPartitionKey(document)) { - erroneousFiles.push(uris[i]); - } - } - if (erroneousFiles.length) { - ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`); - erroneousFiles.forEach(file => ext.outputChannel.appendLine(file.path)); - ext.outputChannel.show(); - throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`); - } - for (const document of documents) { - const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document); - if (retrieved.id) { - ids.push(retrieved.id); - } - } - const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; - for (const id of ids) { - ext.outputChannel.appendLine(`Inserted document: ${id}`); - } - return result; +async function insertDocumentsIntoDocdb( + collectionNode: DocDBCollectionTreeItem, + documents: any[], + uris: vscode.Uri[] +): Promise { + const ids: string[] = []; + let i = 0; + const erroneousFiles: vscode.Uri[] = []; + for (i = 0; i < documents.length; i++) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const document: ItemDefinition = documents[i]; + if ( + !collectionNode.documentsTreeItem.documentHasPartitionKey(document) + ) { + erroneousFiles.push(uris[i]); + } + } + if (erroneousFiles.length) { + ext.outputChannel.appendLog( + `The following documents do not contain the required partition key:` + ); + erroneousFiles.forEach((file) => + ext.outputChannel.appendLine(file.path) + ); + ext.outputChannel.show(); + throw new Error( + `See output for list of documents that do not contain the partition key '${ + nonNullProp(collectionNode, "partitionKey").paths[0] + }' required by collection '${collectionNode.label}'` + ); + } + for (const document of documents) { + const retrieved: ItemDefinition = + await collectionNode.documentsTreeItem.createDocument(document); + if (retrieved.id) { + ids.push(retrieved.id); + } + } + const result: string = `Import into SQL successful. Inserted ${ids.length} document(s). See output for more details.`; + for (const id of ids) { + ext.outputChannel.appendLine(`Inserted document: ${id}`); + } + return result; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise { - let output = ""; - const parsed = await node.collection.insertMany(documents); - if (parsed.result && parsed.result.ok) { - output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; - for (const inserted of Object.values(parsed.insertedIds)) { - ext.outputChannel.appendLine(`Inserted document: ${inserted}`); - } - } - return output; +async function insertDocumentsIntoMongo( + node: MongoCollectionTreeItem, + documents: any[] +): Promise { + let output = ""; + const parsed = await node.collection.insertMany(documents); + if (parsed.result && parsed.result.ok) { + output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`; + for (const inserted of Object.values(parsed.insertedIds)) { + ext.outputChannel.appendLine(`Inserted document: ${inserted}`); + } + } + return output; } diff --git a/Source/docdb/docDBConnectionStrings.ts b/Source/docdb/docDBConnectionStrings.ts index 946490d21..3389eeea4 100644 --- a/Source/docdb/docDBConnectionStrings.ts +++ b/Source/docdb/docDBConnectionStrings.ts @@ -3,40 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as url from 'url'; -import { ParsedConnectionString } from '../ParsedConnectionString'; -import { nonNullProp } from '../utils/nonNull'; +import * as url from "url"; +import { ParsedConnectionString } from "../ParsedConnectionString"; +import { nonNullProp } from "../utils/nonNull"; -export function parseDocDBConnectionString(connectionString: string): ParsedDocDBConnectionString { - const endpoint = getPropertyFromConnectionString(connectionString, 'AccountEndpoint'); - const masterKey = getPropertyFromConnectionString(connectionString, 'AccountKey'); - const databaseName = getPropertyFromConnectionString(connectionString, 'Database'); - if (!endpoint || !masterKey) { - throw new Error('Invalid Document DB connection string.'); - } - return new ParsedDocDBConnectionString(connectionString, endpoint, masterKey, databaseName); +export function parseDocDBConnectionString( + connectionString: string +): ParsedDocDBConnectionString { + const endpoint = getPropertyFromConnectionString( + connectionString, + "AccountEndpoint" + ); + const masterKey = getPropertyFromConnectionString( + connectionString, + "AccountKey" + ); + const databaseName = getPropertyFromConnectionString( + connectionString, + "Database" + ); + if (!endpoint || !masterKey) { + throw new Error("Invalid Document DB connection string."); + } + return new ParsedDocDBConnectionString( + connectionString, + endpoint, + masterKey, + databaseName + ); } -function getPropertyFromConnectionString(connectionString: string, property: string): string | undefined { - const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, 'i'); - const match = connectionString.match(regexp); - return match ? match[1] : undefined; +function getPropertyFromConnectionString( + connectionString: string, + property: string +): string | undefined { + const regexp = new RegExp(`(?:^|;)\\s*${property}=([^;]+)(?:;|$)`, "i"); + const match = connectionString.match(regexp); + return match ? match[1] : undefined; } export class ParsedDocDBConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - public readonly documentEndpoint: string; - public readonly masterKey: string; + public readonly documentEndpoint: string; + public readonly masterKey: string; - constructor(connectionString: string, endpoint: string, masterKey: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.documentEndpoint = endpoint; - this.masterKey = masterKey; + constructor( + connectionString: string, + endpoint: string, + masterKey: string, + databaseName: string | undefined + ) { + super(connectionString, databaseName); + this.documentEndpoint = endpoint; + this.masterKey = masterKey; - const parsedEndpoint = url.parse(endpoint); - this.hostName = nonNullProp(parsedEndpoint, 'hostname'); - this.port = nonNullProp(parsedEndpoint, 'port'); - } + const parsedEndpoint = url.parse(endpoint); + this.hostName = nonNullProp(parsedEndpoint, "hostname"); + this.port = nonNullProp(parsedEndpoint, "port"); + } } diff --git a/Source/docdb/getCosmosClient.ts b/Source/docdb/getCosmosClient.ts index 3b285fc9c..f422ec3c2 100644 --- a/Source/docdb/getCosmosClient.ts +++ b/Source/docdb/getCosmosClient.ts @@ -6,14 +6,33 @@ import { CosmosClient } from "@azure/cosmos"; import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; import * as https from "https"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { ext } from "../extensionVariables"; -export function getCosmosClient(endpoint: string, key: string, isEmulator: boolean | undefined): CosmosClient { - - const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.vsCode.proxyStrictSSL); - const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get(ext.settingsKeys.enableEndpointDiscovery); - const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery }; - return new CosmosClient({ endpoint, key, userAgentSuffix: appendExtensionUserAgent(), agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }), connectionPolicy: connectionPolicy }); - +export function getCosmosClient( + endpoint: string, + key: string, + isEmulator: boolean | undefined +): CosmosClient { + const vscodeStrictSSL: boolean | undefined = vscode.workspace + .getConfiguration() + .get(ext.settingsKeys.vsCode.proxyStrictSSL); + const enableEndpointDiscovery: boolean | undefined = vscode.workspace + .getConfiguration() + .get(ext.settingsKeys.enableEndpointDiscovery); + const connectionPolicy = { + enableEndpointDiscovery: + enableEndpointDiscovery === undefined + ? true + : enableEndpointDiscovery, + }; + return new CosmosClient({ + endpoint, + key, + userAgentSuffix: appendExtensionUserAgent(), + agent: new https.Agent({ + rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL, + }), + connectionPolicy: connectionPolicy, + }); } diff --git a/Source/docdb/registerDocDBCommands.ts b/Source/docdb/registerDocDBCommands.ts index 5eb7545e4..a8f29c69d 100644 --- a/Source/docdb/registerDocDBCommands.ts +++ b/Source/docdb/registerDocDBCommands.ts @@ -3,7 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { + AzExtTreeItem, + IActionContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; import { commands } from "vscode"; import { doubleClickDebounceDelay, sqlFilter } from "../constants"; import { ext } from "../extensionVariables"; @@ -16,89 +21,170 @@ import { DocDBStoredProceduresTreeItem } from "./tree/DocDBStoredProceduresTreeI import { DocDBStoredProcedureTreeItem } from "./tree/DocDBStoredProcedureTreeItem"; export function registerDocDBCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDatabase', createDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBCollection', createDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBDocument', async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentsTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openDocument", documentNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProceduresTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProceduresTreeItem.contextValue); - } - const childNode = await node.createChild(context); - await commands.executeCommand("cosmosDB.openStoredProcedure", childNode); - - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDatabase', deleteDocDBDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBDocument', async (context: IActionContext, node?: DocDBDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', async (context: IActionContext, node?: DocDBStoredProcedureTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBStoredProcedureTreeItem.contextValue); - - } - await node.deleteTreeItem(context); - }); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBDatabase", + createDocDBDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBCollection", + createDocDBCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBDocument", + async (context: IActionContext, node?: DocDBDocumentsTreeItem) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDocumentsTreeItem.contextValue + ); + } + const documentNode = ( + await node.createChild(context) + ); + await commands.executeCommand( + "cosmosDB.openDocument", + documentNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createDocDBStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProceduresTreeItem + ) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProceduresTreeItem.contextValue + ); + } + const childNode = await node.createChild(context); + await commands.executeCommand( + "cosmosDB.openStoredProcedure", + childNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBDatabase", + deleteDocDBDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBCollection", + deleteDocDBCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProcedureTreeItem + ) => { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProcedureTreeItem.contextValue + ); + } + await ext.fileSystem.showTextDocument(node); + }, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBDocument", + async (context: IActionContext, node?: DocDBDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDocumentTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteDocDBStoredProcedure", + async ( + context: IActionContext, + node?: DocDBStoredProcedureTreeItem + ) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBStoredProcedureTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); } -export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context); - } - const databaseNode: DocDBDatabaseTreeItem = await node.createChild(context); - await databaseNode.createChild(context); +export async function createDocDBDatabase( + context: IActionContext, + node?: DocDBAccountTreeItem +): Promise { + if (!node) { + node = await pickDocDBAccount(context); + } + const databaseNode: DocDBDatabaseTreeItem = ( + await node.createChild(context) + ); + await databaseNode.createChild(context); } -export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.createChild(context); +export async function createDocDBCollection( + context: IActionContext, + node?: DocDBDatabaseTreeItem +): Promise { + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDatabaseTreeItem.contextValue + ); + } + await node.createChild(context); } -export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteDocDBDatabase( + context: IActionContext, + node?: DocDBDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickDocDBAccount(context, DocDBCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteDocDBCollection( + context: IActionContext, + node?: DocDBCollectionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickDocDBAccount( + context, + DocDBCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -async function pickDocDBAccount(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - sqlFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickDocDBAccount( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [sqlFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/docdb/tree/DocDBAccountTreeItem.ts b/Source/docdb/tree/DocDBAccountTreeItem.ts index 0cee7ed06..242af5546 100644 --- a/Source/docdb/tree/DocDBAccountTreeItem.ts +++ b/Source/docdb/tree/DocDBAccountTreeItem.ts @@ -3,35 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; +import { DatabaseDefinition, Resource } from "@azure/cosmos"; +import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBDocumentServer"; - public contextValue: string = DocDBAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBDocumentServer"; + public contextValue: string = DocDBAccountTreeItem.contextValue; - public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem { - this.valuesToMask.push(resource._rid, resource._self); - return new DocDBDatabaseTreeItem(this, resource); - } + public initChild( + resource: DatabaseDefinition & Resource + ): DocDBDatabaseTreeItem { + this.valuesToMask.push(resource._rid, resource._self); + return new DocDBDatabaseTreeItem(this, resource); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case DocDBDatabaseTreeItem.contextValue: - case DocDBCollectionTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case DocDBDocumentsTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case DocDBDatabaseTreeItem.contextValue: + case DocDBCollectionTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case DocDBDocumentsTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/docdb/tree/DocDBAccountTreeItemBase.ts b/Source/docdb/tree/DocDBAccountTreeItemBase.ts index da9eec6b7..2984b29ef 100644 --- a/Source/docdb/tree/DocDBAccountTreeItemBase.ts +++ b/Source/docdb/tree/DocDBAccountTreeItemBase.ts @@ -3,93 +3,139 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { SERVERLESS_CAPABILITY_NAME, getThemeAgnosticIconPath } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { rejectOnTimeout } from '../../utils/timeout'; -import { getCosmosClient } from '../getCosmosClient'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { + CosmosClient, + DatabaseDefinition, + DatabaseResponse, + FeedOptions, + QueryIterator, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { + SERVERLESS_CAPABILITY_NAME, + getThemeAgnosticIconPath, +} from "../../constants"; +import { nonNullProp } from "../../utils/nonNull"; +import { rejectOnTimeout } from "../../utils/timeout"; +import { getCosmosClient } from "../getCosmosClient"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class provides common logic for DocumentDB, Graph, and Table accounts * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase { - public readonly label: string; - public readonly childTypeLabel: string = "Database"; +export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase< + DatabaseDefinition & Resource +> { + public readonly label: string; + public readonly childTypeLabel: string = "Database"; + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + endpoint: string, + masterKey: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super(parent); + this.id = id; + this.label = label; + this.root = { + endpoint, + masterKey, + isEmulator, + getCosmosClient: () => + getCosmosClient(endpoint, masterKey, isEmulator), + }; - constructor(parent: AzExtParentTreeItem, id: string, label: string, endpoint: string, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.root = { - endpoint, - masterKey, - isEmulator, - getCosmosClient: () => getCosmosClient(endpoint, masterKey, isEmulator) - }; + this.valuesToMask.push(id, endpoint, masterKey); + } - this.valuesToMask.push(id, endpoint, masterKey); - } + public get connectionString(): string { + return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; + } - public get connectionString(): string { - return `AccountEndpoint=${this.root.endpoint};AccountKey=${this.root.masterKey}`; - } + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("CosmosDBAccount.svg"); + } - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } + public get isServerless(): boolean { + return this.databaseAccount?.capabilities + ? this.databaseAccount.capabilities.some( + (cap) => cap.name === SERVERLESS_CAPABILITY_NAME + ) + : false; + } - public get isServerless(): boolean { - return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false; + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return client.databases.readAll(feedOptions); + } - } + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + validateInput: validateDatabaseName, + stepName: "createDatabase", + }); - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.databases.readAll(feedOptions); - } + const client = this.root.getCosmosClient(); + const database: DatabaseResponse = await client.databases.create({ + id: databaseName, + }); + return this.initChild(nonNullProp(database, "resource")); + } - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: 'Database Name', - validateInput: validateDatabaseName, - stepName: 'createDatabase' - }); + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (this.root.isEmulator) { + const unableToReachEmulatorMessage: string = + "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; + return await rejectOnTimeout( + 2000, + () => super.loadMoreChildrenImpl(clearCache), + unableToReachEmulatorMessage + ); + } else { + return await super.loadMoreChildrenImpl(clearCache); + } + } - const client = this.root.getCosmosClient(); - const database: DatabaseResponse = await client.databases.create({ id: databaseName }); - return this.initChild(nonNullProp(database, 'resource')); - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (this.root.isEmulator) { - const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again."; - return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage); - } else { - return await super.loadMoreChildrenImpl(clearCache); - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } } function validateDatabaseName(name: string): string | undefined | null { - if (!name || name.length < 1 || name.length > 255) { - return "Name has to be between 1 and 255 chars long"; - } - if (name.endsWith(" ")) { - return "Database name cannot end with space"; - } - if (/[/\\?#=]/.test(name)) { - return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; - } - return undefined; + if (!name || name.length < 1 || name.length > 255) { + return "Name has to be between 1 and 255 chars long"; + } + if (name.endsWith(" ")) { + return "Database name cannot end with space"; + } + if (/[/\\?#=]/.test(name)) { + return `Database name cannot contain the characters '\\', '/', '#', '?', '='`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBCollectionTreeItem.ts b/Source/docdb/tree/DocDBCollectionTreeItem.ts index 987bbe3b4..8849bee34 100644 --- a/Source/docdb/tree/DocDBCollectionTreeItem.ts +++ b/Source/docdb/tree/DocDBCollectionTreeItem.ts @@ -3,90 +3,115 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { + Container, + ContainerDefinition, + CosmosClient, + PartitionKeyDefinition, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { DocDBDatabaseTreeItem } from "./DocDBDatabaseTreeItem"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * Represents a DocumentDB collection */ export class DocDBCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBDocumentCollection"; - public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; - public readonly documentsTreeItem: DocDBDocumentsTreeItem; - public readonly parent: DocDBDatabaseTreeItem; - - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) { - super(parent); - this.parent = parent; - this.documentsTreeItem = new DocDBDocumentsTreeItem(this); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._container.id; - } - - public get label(): string { - return this._container.id; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get link(): string { - return this._container._self; - } - - public get partitionKey(): PartitionKeyDefinition | undefined { - return this._container.partitionKey; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this.documentsTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case DocDBDocumentsTreeItem.contextValue: - case DocDBDocumentTreeItem.contextValue: - return this.documentsTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - } + public static contextValue: string = "cosmosDBDocumentCollection"; + public readonly contextValue: string = DocDBCollectionTreeItem.contextValue; + public readonly documentsTreeItem: DocDBDocumentsTreeItem; + public readonly parent: DocDBDatabaseTreeItem; + + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + constructor( + parent: DocDBDatabaseTreeItem, + private _container: ContainerDefinition & Resource + ) { + super(parent); + this.parent = parent; + this.documentsTreeItem = new DocDBDocumentsTreeItem(this); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( + this + ); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._container.id; + } + + public get label(): string { + return this._container.id; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get link(): string { + return this._container._self; + } + + public get partitionKey(): PartitionKeyDefinition | undefined { + return this._container.partitionKey; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteCollection" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return [this.documentsTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public pickTreeItemImpl( + expectedContextValues: (string | RegExp)[] + ): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case DocDBDocumentsTreeItem.contextValue: + case DocDBDocumentTreeItem.contextValue: + return this.documentsTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getDatabaseClient(client).container(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItem.ts b/Source/docdb/tree/DocDBDatabaseTreeItem.ts index ee8c23694..b51504cc2 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItem.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItem.ts @@ -3,20 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase'; +import { + ContainerDefinition, + CosmosClient, + Database, + Resource, +} from "@azure/cosmos"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDatabaseTreeItemBase } from "./DocDBDatabaseTreeItemBase"; export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBDocumentDatabase"; - public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Collection'; + public static contextValue: string = "cosmosDBDocumentDatabase"; + public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; - public initChild(container: ContainerDefinition & Resource): DocDBCollectionTreeItem { - return new DocDBCollectionTreeItem(this, container); - } + public initChild( + container: ContainerDefinition & Resource + ): DocDBCollectionTreeItem { + return new DocDBCollectionTreeItem(this, container); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); - } + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } } diff --git a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts index aa7e8d779..15a935e5c 100644 --- a/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts +++ b/Source/docdb/tree/DocDBDatabaseTreeItemBase.ts @@ -3,12 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { + ContainerDefinition, + ContainerResponse, + CosmosClient, + DatabaseDefinition, + FeedOptions, + QueryIterator, + RequestOptions, + Resource, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBAccountTreeItemBase } from "./DocDBAccountTreeItemBase"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; const minThroughputFixed: number = 400; const minThroughputPartitioned: number = 400; @@ -19,143 +34,177 @@ const throughputStepSize = 100; * This class provides common logic for DocumentDB, Graph, and Table databases * (DocumentDB is the base type for all Cosmos DB accounts) */ -export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase { - public readonly parent: DocDBAccountTreeItemBase; - private readonly _database: DatabaseDefinition & Resource; - - constructor(parent: DocDBAccountTreeItemBase, database: DatabaseDefinition & Resource) { - super(parent); - this._database = database; - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public get id(): string { - return nonNullProp(this._database, 'id'); - } - - public get label(): string { - return nonNullProp(this._database, 'id'); - } - - public get link(): string { - return nonNullProp(this._database, '_self'); - } - - public get connectionString(): string { - return this.parent.connectionString.concat(`;Database=${this.id}`); - } - - public get databaseName(): string { - return this._database.id; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return client.database(this._database.id).containers.readAll(feedOptions); - } - - // Delete the database - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await client.database(this.id).delete(); - } - - // Create a DB collection - public async createChildImpl(context: ICreateChildImplContext): Promise { - const containerName = await context.ui.showInputBox({ - placeHolder: `Enter an id for your ${this.childTypeLabel}`, - validateInput: validateCollectionName, - stepName: `create${this.childTypeLabel}` - }); - - const containerDefinition: ContainerDefinition = { - id: containerName - }; - - const partitionKey = await this.getNewPartitionKey(context); - if (partitionKey) { - containerDefinition.partitionKey = { - paths: [partitionKey] - }; - } - const options: RequestOptions = {}; - - if (!this.parent.isServerless) { - const isFixed: boolean = !(containerDefinition.partitionKey); - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const throughput: number = Number(await context.ui.showInputBox({ - value: minThroughput.toString(), - prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, - stepName: 'throughputCapacity', - validateInput: (input: string) => validateThroughput(isFixed, input) - })); - - if (throughput !== 0) { - options.offerThroughput = throughput; - } - } - - context.showCreatingTreeItem(containerName); - const client = this.root.getCosmosClient(); - const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options); - - return this.initChild(nonNullProp(container, 'resource')); - } - - protected async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address/zipCode' - }); - - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } - - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - return undefined; - } +export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase< + ContainerDefinition & Resource +> { + public readonly parent: DocDBAccountTreeItemBase; + private readonly _database: DatabaseDefinition & Resource; + + constructor( + parent: DocDBAccountTreeItemBase, + database: DatabaseDefinition & Resource + ) { + super(parent); + this._database = database; + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("database"); + } + + public get id(): string { + return nonNullProp(this._database, "id"); + } + + public get label(): string { + return nonNullProp(this._database, "id"); + } + + public get link(): string { + return nonNullProp(this._database, "_self"); + } + + public get connectionString(): string { + return this.parent.connectionString.concat(`;Database=${this.id}`); + } + + public get databaseName(): string { + return this._database.id; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return client + .database(this._database.id) + .containers.readAll(feedOptions); + } + + // Delete the database + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteDatabase" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await client.database(this.id).delete(); + } + + // Create a DB collection + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const containerName = await context.ui.showInputBox({ + placeHolder: `Enter an id for your ${this.childTypeLabel}`, + validateInput: validateCollectionName, + stepName: `create${this.childTypeLabel}`, + }); + + const containerDefinition: ContainerDefinition = { + id: containerName, + }; + + const partitionKey = await this.getNewPartitionKey(context); + if (partitionKey) { + containerDefinition.partitionKey = { + paths: [partitionKey], + }; + } + const options: RequestOptions = {}; + + if (!this.parent.isServerless) { + const isFixed: boolean = !containerDefinition.partitionKey; + const minThroughput = isFixed + ? minThroughputFixed + : minThroughputPartitioned; + const throughput: number = Number( + await context.ui.showInputBox({ + value: minThroughput.toString(), + prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`, + stepName: "throughputCapacity", + validateInput: (input: string) => + validateThroughput(isFixed, input), + }) + ); + + if (throughput !== 0) { + options.offerThroughput = throughput; + } + } + + context.showCreatingTreeItem(containerName); + const client = this.root.getCosmosClient(); + const container: ContainerResponse = await client + .database(this.id) + .containers.create(containerDefinition, options); + + return this.initChild(nonNullProp(container, "resource")); + } + + protected async getNewPartitionKey( + context: IActionContext + ): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: "Enter the partition key for the collection, or leave blank for fixed size.", + stepName: "partitionKeyForCollection", + validateInput: this.validatePartitionKey, + placeHolder: "e.g. /address/zipCode", + }); + + if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { + partitionKey = "/" + partitionKey; + } + + return partitionKey; + } + + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + return undefined; + } } -function validateThroughput(isFixed: boolean, input: string): string | undefined | null { - if (input === "0") { - return undefined; - } - - try { - const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned; - const value = Number(input); - if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) { - return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; - } - } catch (err) { - return "Input must be a number"; - } - return undefined; +function validateThroughput( + isFixed: boolean, + input: string +): string | undefined | null { + if (input === "0") { + return undefined; + } + + try { + const minThroughput = isFixed + ? minThroughputFixed + : minThroughputPartitioned; + const value = Number(input); + if ( + value < minThroughput || + value > maxThroughput || + (value - minThroughput) % throughputStepSize !== 0 + ) { + return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`; + } + } catch (err) { + return "Input must be a number"; + } + return undefined; } function validateCollectionName(name: string): string | undefined | null { - if (!name) { - return "Collection name cannot be empty"; - } - if (name.endsWith(" ")) { - return "Collection name cannot end with space"; - } - if (/[/\\?#]/.test(name)) { - return `Collection name cannot contain the characters '\\', '/', '#', '?'`; - } - return undefined; + if (!name) { + return "Collection name cannot be empty"; + } + if (name.endsWith(" ")) { + return "Collection name cannot end with space"; + } + if (/[/\\?#]/.test(name)) { + return `Collection name cannot contain the characters '\\', '/', '#', '?'`; + } + return undefined; } diff --git a/Source/docdb/tree/DocDBDocumentTreeItem.ts b/Source/docdb/tree/DocDBDocumentTreeItem.ts index 1505572d9..408dedfd7 100644 --- a/Source/docdb/tree/DocDBDocumentTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentTreeItem.ts @@ -3,131 +3,171 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem'; -import { sanitizeId } from './DocDBUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; - -const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']; +import { + CosmosClient, + Item, + ItemDefinition, + RequestOptions, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullProp } from "../../utils/nonNull"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { DocDBDocumentsTreeItem } from "./DocDBDocumentsTreeItem"; +import { sanitizeId } from "./DocDBUtils"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; + +const hiddenFields: string[] = [ + "_rid", + "_self", + "_etag", + "_attachments", + "_ts", +]; /** * Represents a Cosmos DB DocumentDB (SQL) document */ -export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBDocument"; - public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; - public readonly parent: DocDBDocumentsTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - private _label: string; - private _document: ItemDefinition; - - constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { - super(parent); - this._document = document; - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openDocument'; - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); - } - - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } - - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this._document); - ext.fileSystem.fireChangedEvent(this); - } - - public get link(): string { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this.document._self; - } - - get document(): ItemDefinition { - return this._document; - } - - get label(): string { - return this._label; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getDocumentClient(client).delete(); - } - - public async getFileContent(): Promise { - const clonedDoc: {} = { ...this.document }; - for (const field of hiddenFields) { - delete clonedDoc[field]; - } - return JSON.stringify(clonedDoc, null, 2); - } - - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const newData = JSON.parse(content); - for (const field of hiddenFields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - newData[field] = this.document[field]; - } - - const client: CosmosClient = this.root.getCosmosClient(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (["_etag"].some((element) => !newData[element])) { - throw new Error(`The "_self" and "_etag" fields are required to update a document`); - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const options: RequestOptions = { accessCondition: { type: 'IfMatch', condition: newData._etag } }; - const response = await this.getDocumentClient(client).replace(newData, options); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this._document = response.resource; - } - } - - private getPartitionKeyValue(): string | undefined | Object { - const partitionKey = this.parent.parent.partitionKey; - if (!partitionKey) { //Fixed collections -> no partitionKeyValue - return undefined; - } - const fields = partitionKey.paths[0].split('/'); - if (fields[0] === '') { - fields.shift(); - } - let value; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - value = value ? value[field] : this.document[field]; - if (!value) { //Partition Key exists, but this document doesn't have a value - return ''; - } - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - } - - private getDocumentClient(client: CosmosClient): Item { - return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue()); - } +export class DocDBDocumentTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "cosmosDBDocument"; + public readonly contextValue: string = DocDBDocumentTreeItem.contextValue; + public readonly parent: DocDBDocumentsTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + private _label: string; + private _document: ItemDefinition; + + constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) { + super(parent); + this._document = document; + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + this.commandId = "cosmosDB.openDocument"; + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return sanitizeId(`${this.document.id}:${this.getPartitionKeyValue()}`); + } + + public get filePath(): string { + return this.label + "-cosmos-document.json"; + } + + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this._document); + ext.fileSystem.fireChangedEvent(this); + } + + public get link(): string { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return this.document._self; + } + + get document(): ItemDefinition { + return this._document; + } + + get label(): string { + return this._label; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("file"); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteDocument" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getDocumentClient(client).delete(); + } + + public async getFileContent(): Promise { + const clonedDoc: {} = { ...this.document }; + for (const field of hiddenFields) { + delete clonedDoc[field]; + } + return JSON.stringify(clonedDoc, null, 2); + } + + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const newData = JSON.parse(content); + for (const field of hiddenFields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + newData[field] = this.document[field]; + } + + const client: CosmosClient = this.root.getCosmosClient(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (["_etag"].some((element) => !newData[element])) { + throw new Error( + `The "_self" and "_etag" fields are required to update a document` + ); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const options: RequestOptions = { + accessCondition: { type: "IfMatch", condition: newData._etag }, + }; + const response = await this.getDocumentClient(client).replace( + newData, + options + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this._document = response.resource; + } + } + + private getPartitionKeyValue(): string | undefined | Object { + const partitionKey = this.parent.parent.partitionKey; + if (!partitionKey) { + //Fixed collections -> no partitionKeyValue + return undefined; + } + const fields = partitionKey.paths[0].split("/"); + if (fields[0] === "") { + fields.shift(); + } + let value; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + value = value ? value[field] : this.document[field]; + if (!value) { + //Partition Key exists, but this document doesn't have a value + return ""; + } + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + } + + private getDocumentClient(client: CosmosClient): Item { + return this.parent + .getContainerClient(client) + .item( + nonNullProp(this.document, "id"), + this.getPartitionKeyValue() + ); + } } diff --git a/Source/docdb/tree/DocDBDocumentsTreeItem.ts b/Source/docdb/tree/DocDBDocumentsTreeItem.ts index b8265444d..ec05451e0 100644 --- a/Source/docdb/tree/DocDBDocumentsTreeItem.ts +++ b/Source/docdb/tree/DocDBDocumentsTreeItem.ts @@ -3,127 +3,160 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos'; -import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { + Container, + CosmosClient, + FeedOptions, + ItemDefinition, + ItemResponse, + QueryIterator, +} from "@azure/cosmos"; +import { + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBDocumentTreeItem } from "./DocDBDocumentTreeItem"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class provides logic for DocumentDB collections */ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase { - public static contextValue: string = "cosmosDBDocumentsGroup"; - public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; - public readonly childTypeLabel: string = "Documents"; - public readonly parent: DocDBCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get id(): string { - return "$Documents"; - } - - public get label(): string { - return "Documents"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).items.readAll(feedOptions); - } - - public initChild(document: ItemDefinition): DocDBDocumentTreeItem { - return new DocDBDocumentTreeItem(this, document); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' }); - - docID = docID.trim(); - let body: ItemDefinition = { id: docID }; - body = (await this.promptForPartitionKey(context, body)); - context.showCreatingTreeItem(docID); - const item: ItemDefinition = await this.createDocument(body); - - return this.initChild(item); - } - - public async createDocument(body: ItemDefinition): Promise { - const item: ItemResponse = await this.getContainerClient(this.root.getCosmosClient()).items.create(body); - return nonNullProp(item, 'resource'); - } - - public documentHasPartitionKey(doc: Object): boolean { - let interim = doc; - let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (!partitionKey) { - return true; - } - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const partitionKeyPath = partitionKey.split('/'); - - for (const prop of partitionKeyPath) { - // eslint-disable-next-line no-prototype-builtins - if (interim.hasOwnProperty(prop)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[prop]; - } else { - return false; - } - } - return true; - } - - public async promptForPartitionKey(context: IActionContext, body: ItemDefinition): Promise { - const partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0]; - if (partitionKey) { - const partitionKeyValue: string = await context.ui.showInputBox({ - prompt: `Enter a value for the partition key ("${partitionKey}")`, - stepName: 'valueforParititionKey' - }); - // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. - // We need to present the partitionKey value as part of the document contents - Object.assign(body, this.createPartitionPathObject(partitionKey, partitionKeyValue)); - } - return body; - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - // Create a nested Object given the partition key path and value - private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object { - //remove leading slash - if (partitionKey[0] === '/') { - partitionKey = partitionKey.slice(1); - } - const keyPath = partitionKey.split('/'); - const PartitionPath: Object = {}; - let interim: Object = PartitionPath; - let i: number; - for (i = 0; i < keyPath.length - 1; i++) { - interim[keyPath[i]] = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - interim = interim[keyPath[i]]; - } - interim[keyPath[i]] = partitionKeyValue; - return PartitionPath; - } + public static contextValue: string = "cosmosDBDocumentsGroup"; + public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue; + public readonly childTypeLabel: string = "Documents"; + public readonly parent: DocDBCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get id(): string { + return "$Documents"; + } + + public get label(): string { + return "Documents"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return this.getContainerClient(client).items.readAll(feedOptions); + } + + public initChild(document: ItemDefinition): DocDBDocumentTreeItem { + return new DocDBDocumentTreeItem(this, document); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + let docID = await context.ui.showInputBox({ + prompt: "Enter a document ID or leave blank for a generated ID", + stepName: "createDocument", + }); + + docID = docID.trim(); + let body: ItemDefinition = { id: docID }; + body = await this.promptForPartitionKey(context, body); + context.showCreatingTreeItem(docID); + const item: ItemDefinition = await this.createDocument(body); + + return this.initChild(item); + } + + public async createDocument(body: ItemDefinition): Promise { + const item: ItemResponse = + await this.getContainerClient( + this.root.getCosmosClient() + ).items.create(body); + return nonNullProp(item, "resource"); + } + + public documentHasPartitionKey(doc: Object): boolean { + let interim = doc; + let partitionKey: string | undefined = + this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (!partitionKey) { + return true; + } + if (partitionKey[0] === "/") { + partitionKey = partitionKey.slice(1); + } + const partitionKeyPath = partitionKey.split("/"); + + for (const prop of partitionKeyPath) { + // eslint-disable-next-line no-prototype-builtins + if (interim.hasOwnProperty(prop)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[prop]; + } else { + return false; + } + } + return true; + } + + public async promptForPartitionKey( + context: IActionContext, + body: ItemDefinition + ): Promise { + const partitionKey: string | undefined = + this.parent.partitionKey && this.parent.partitionKey.paths[0]; + if (partitionKey) { + const partitionKeyValue: string = await context.ui.showInputBox({ + prompt: `Enter a value for the partition key ("${partitionKey}")`, + stepName: "valueforParititionKey", + }); + // Unlike delete/replace, createDocument does not accept a partition key value via an options parameter. + // We need to present the partitionKey value as part of the document contents + Object.assign( + body, + this.createPartitionPathObject(partitionKey, partitionKeyValue) + ); + } + return body; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + // Create a nested Object given the partition key path and value + private createPartitionPathObject( + partitionKey: string, + partitionKeyValue: string + ): Object { + //remove leading slash + if (partitionKey[0] === "/") { + partitionKey = partitionKey.slice(1); + } + const keyPath = partitionKey.split("/"); + const PartitionPath: Object = {}; + let interim: Object = PartitionPath; + let i: number; + for (i = 0; i < keyPath.length - 1; i++) { + interim[keyPath[i]] = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + interim = interim[keyPath[i]]; + } + interim[keyPath[i]] = partitionKeyValue; + return PartitionPath; + } } diff --git a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts index 899eccd27..20ced0d3e 100644 --- a/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProcedureTreeItem.ts @@ -3,74 +3,100 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBStoredProceduresTreeItem } from "./DocDBStoredProceduresTreeItem"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * Represents a Cosmos DB DocumentDB (SQL) stored procedure */ -export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "cosmosDBStoredProcedure"; - public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue; - public readonly cTime: number = Date.now(); - public readonly parent: DocDBStoredProceduresTreeItem; - public mTime: number = Date.now(); +export class DocDBStoredProcedureTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "cosmosDBStoredProcedure"; + public readonly contextValue: string = + DocDBStoredProcedureTreeItem.contextValue; + public readonly cTime: number = Date.now(); + public readonly parent: DocDBStoredProceduresTreeItem; + public mTime: number = Date.now(); - constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) { - super(parent); - ext.fileSystem.fireChangedEvent(this); - this.commandId = 'cosmosDB.openStoredProcedure'; - } + constructor( + parent: DocDBStoredProceduresTreeItem, + public procedure: StoredProcedureDefinition & Resource + ) { + super(parent); + ext.fileSystem.fireChangedEvent(this); + this.commandId = "cosmosDB.openStoredProcedure"; + } - public get root(): IDocDBTreeRoot { - return this.parent.root; - } + public get root(): IDocDBTreeRoot { + return this.parent.root; + } - public get filePath(): string { - return this.label + '-cosmos-stored-procedure.js'; - } + public get filePath(): string { + return this.label + "-cosmos-stored-procedure.js"; + } - public get id(): string { - return this.procedure.id; - } + public get id(): string { + return this.procedure.id; + } - public get label(): string { - return this.procedure.id; - } + public get label(): string { + return this.procedure.id; + } - public get link(): string { - return this.procedure._self; - } + public get link(): string { + return this.procedure._self; + } - public async getFileContent(): Promise { - return typeof this.procedure.body === 'string' ? this.procedure.body : ''; + public async getFileContent(): Promise { + return typeof this.procedure.body === "string" + ? this.procedure.body + : ""; + } - } + public async refreshImpl(): Promise { + ext.fileSystem.fireChangedEvent(this); + } - public async refreshImpl(): Promise { - ext.fileSystem.fireChangedEvent(this); - } + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + const client = this.root.getCosmosClient(); + const replace = await this.parent + .getContainerClient(client) + .scripts.storedProcedure(this.id) + .replace({ id: this.id, body: content }); + this.procedure = nonNullProp(replace, "resource"); + } - public async writeFileContent(_context: IActionContext, content: string): Promise { - const client = this.root.getCosmosClient(); - const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content }); - this.procedure = nonNullProp(replace, 'resource'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("server-process"); + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete(); - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete stored procedure '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteStoredProcedure" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.parent + .getContainerClient(client) + .scripts.storedProcedure(this.id) + .delete(); + } } diff --git a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts index 4c3ddfd1a..a869e8a99 100644 --- a/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts +++ b/Source/docdb/tree/DocDBStoredProceduresTreeItem.ts @@ -3,95 +3,141 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos'; -import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; +import { + Container, + CosmosClient, + FeedOptions, + QueryIterator, + Resource, + StoredProcedureDefinition, +} from "@azure/cosmos"; +import { + AzExtTreeItem, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; -import { defaultStoredProcedure } from '../../constants'; -import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem'; -import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem'; -import { DocDBTreeItemBase } from './DocDBTreeItemBase'; +import { defaultStoredProcedure } from "../../constants"; +import { GraphCollectionTreeItem } from "../../graph/tree/GraphCollectionTreeItem"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { DocDBCollectionTreeItem } from "./DocDBCollectionTreeItem"; +import { DocDBStoredProcedureTreeItem } from "./DocDBStoredProcedureTreeItem"; +import { DocDBTreeItemBase } from "./DocDBTreeItemBase"; /** * This class represents the DocumentDB "Stored Procedures" node in the tree */ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase { - - public static contextValue: string = "cosmosDBStoredProceduresGroup"; - public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue; - public readonly childTypeLabel: string = "Stored Procedure"; - public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; - public suppressMaskLabel = true; - - constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { - super(parent); - this.root = this.parent.root; - } - - public initChild(resource: StoredProcedureDefinition & Resource): DocDBStoredProcedureTreeItem { - return new DocDBStoredProcedureTreeItem(this, resource); - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('server-process'); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const client = this.root.getCosmosClient(); - const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context); - const currStoredProcedureNames: string[] = []; - for (const sp of currStoredProcedureList) { - currStoredProcedureNames.push(nonNullProp(sp, "id")); - } - const spID = (await context.ui.showInputBox({ - prompt: "Enter a unique stored procedure ID", - stepName: 'createStoredProcedure', - validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames) - })).trim(); - const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure }; - context.showCreatingTreeItem(spID); - const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body); - - return this.initChild(nonNullProp(sproc, 'resource')); - } - - public get id(): string { - return "$StoredProcedures"; - } - - public get label(): string { - return "Stored Procedures"; - } - - public get link(): string { - return this.parent.link; - } - - public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator { - return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions); - } - - public getContainerClient(client: CosmosClient): Container { - return this.parent.getContainerClient(client); - } - - private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined { - if (name.length < 1 || name.length > 255) { - return localize("nameLength", "Name has to be between 1 and 255 chars long"); - } - - if (/[/\\?#&]/.test(name)) { - return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &"); - } - if (name[name.length - 1] === " ") { - return localize("endsWithSpace", "Name cannot end with a space."); - } - if (currStoredProcedureNames.includes(name)) { - return localize('nameExists', 'Stored Procedure "{0}" already exists.', name); - } - - return undefined; - } + public static contextValue: string = "cosmosDBStoredProceduresGroup"; + public readonly contextValue: string = + DocDBStoredProceduresTreeItem.contextValue; + public readonly childTypeLabel: string = "Stored Procedure"; + public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem; + public suppressMaskLabel = true; + + constructor(parent: DocDBCollectionTreeItem | GraphCollectionTreeItem) { + super(parent); + this.root = this.parent.root; + } + + public initChild( + resource: StoredProcedureDefinition & Resource + ): DocDBStoredProcedureTreeItem { + return new DocDBStoredProcedureTreeItem(this, resource); + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("server-process"); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const client = this.root.getCosmosClient(); + const currStoredProcedureList: AzExtTreeItem[] = + await this.getCachedChildren(context); + const currStoredProcedureNames: string[] = []; + for (const sp of currStoredProcedureList) { + currStoredProcedureNames.push(nonNullProp(sp, "id")); + } + const spID = ( + await context.ui.showInputBox({ + prompt: "Enter a unique stored procedure ID", + stepName: "createStoredProcedure", + validateInput: (name: string) => + this.validateStoredProcedureName( + name, + currStoredProcedureNames + ), + }) + ).trim(); + const body: StoredProcedureDefinition = { + id: spID, + body: defaultStoredProcedure, + }; + context.showCreatingTreeItem(spID); + const sproc = + await this.getContainerClient( + client + ).scripts.storedProcedures.create(body); + + return this.initChild(nonNullProp(sproc, "resource")); + } + + public get id(): string { + return "$StoredProcedures"; + } + + public get label(): string { + return "Stored Procedures"; + } + + public get link(): string { + return this.parent.link; + } + + public getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator { + return this.getContainerClient(client).scripts.storedProcedures.readAll( + feedOptions + ); + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getContainerClient(client); + } + + private validateStoredProcedureName( + name: string, + currStoredProcedureNames: string[] + ): string | undefined { + if (name.length < 1 || name.length > 255) { + return localize( + "nameLength", + "Name has to be between 1 and 255 chars long" + ); + } + + if (/[/\\?#&]/.test(name)) { + return localize( + "illegalChars", + "Name contains illegal chars: /, \\, ?, #, &" + ); + } + if (name[name.length - 1] === " ") { + return localize("endsWithSpace", "Name cannot end with a space."); + } + if (currStoredProcedureNames.includes(name)) { + return localize( + "nameExists", + 'Stored Procedure "{0}" already exists.', + name + ); + } + + return undefined; + } } diff --git a/Source/docdb/tree/DocDBTreeItemBase.ts b/Source/docdb/tree/DocDBTreeItemBase.ts index 4424603ae..0774fbcdc 100644 --- a/Source/docdb/tree/DocDBTreeItemBase.ts +++ b/Source/docdb/tree/DocDBTreeItemBase.ts @@ -3,53 +3,64 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { IDocDBTreeRoot } from './IDocDBTreeRoot'; +import { CosmosClient, FeedOptions, QueryIterator } from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, +} from "@microsoft/vscode-azext-utils"; +import { getBatchSizeSetting } from "../../utils/workspacUtils"; +import { IDocDBTreeRoot } from "./IDocDBTreeRoot"; /** * This class provides common iteration logic for DocumentDB accounts, databases, and collections */ export abstract class DocDBTreeItemBase extends AzExtParentTreeItem { - public abstract readonly label: string; - public abstract readonly contextValue: string; - public abstract readonly childTypeLabel: string; + public abstract readonly label: string; + public abstract readonly contextValue: string; + public abstract readonly childTypeLabel: string; - private _hasMoreChildren: boolean = true; - private _iterator: QueryIterator | undefined; - private _batchSize: number = getBatchSizeSetting(); + private _hasMoreChildren: boolean = true; + private _iterator: QueryIterator | undefined; + private _batchSize: number = getBatchSizeSetting(); - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } - public root: IDocDBTreeRoot; + public root: IDocDBTreeRoot; - public abstract initChild(resource: T): AzExtTreeItem; + public abstract initChild(resource: T): AzExtTreeItem; - public abstract getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator; + public abstract getIterator( + client: CosmosClient, + feedOptions: FeedOptions + ): QueryIterator; - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - } + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + } - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._iterator === undefined) { - this._hasMoreChildren = true; - const client = this.root.getCosmosClient(); - this._iterator = this.getIterator(client, { maxItemCount: this._batchSize }); - } + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache || this._iterator === undefined) { + this._hasMoreChildren = true; + const client = this.root.getCosmosClient(); + this._iterator = this.getIterator(client, { + maxItemCount: this._batchSize, + }); + } - const resourceArray: T[] = []; - const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()).resources; - if (resourceFeed) { - resourceArray.push(...resourceFeed); - } - this._hasMoreChildren = this._iterator.hasMoreResults(); + const resourceArray: T[] = []; + const resourceFeed: T[] | undefined = (await this._iterator.fetchNext()) + .resources; + if (resourceFeed) { + resourceArray.push(...resourceFeed); + } + this._hasMoreChildren = this._iterator.hasMoreResults(); - this._batchSize *= 2; + this._batchSize *= 2; - return resourceArray.map((resource: T) => this.initChild(resource)); - } + return resourceArray.map((resource: T) => this.initChild(resource)); + } } diff --git a/Source/docdb/tree/DocDBUtils.ts b/Source/docdb/tree/DocDBUtils.ts index 3d45cf950..1a0630d53 100644 --- a/Source/docdb/tree/DocDBUtils.ts +++ b/Source/docdb/tree/DocDBUtils.ts @@ -8,5 +8,5 @@ * Learn more at: https://github.com/ljharb/qs#rfc-3986-and-rfc-1738-space-encoding */ export function sanitizeId(id: string): string { - return id.replace(/\+/g, ' '); + return id.replace(/\+/g, " "); } diff --git a/Source/docdb/tree/IDocDBTreeRoot.ts b/Source/docdb/tree/IDocDBTreeRoot.ts index 9179eb454..6827564c2 100644 --- a/Source/docdb/tree/IDocDBTreeRoot.ts +++ b/Source/docdb/tree/IDocDBTreeRoot.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -7,8 +6,8 @@ import { CosmosClient } from "@azure/cosmos"; export interface IDocDBTreeRoot { - endpoint: string; - masterKey: string; - isEmulator: boolean | undefined; - getCosmosClient(): CosmosClient; + endpoint: string; + masterKey: string; + isEmulator: boolean | undefined; + getCosmosClient(): CosmosClient; } diff --git a/Source/graph/gremlinEndpoints.ts b/Source/graph/gremlinEndpoints.ts index 1ef6b283d..0bbeae16f 100644 --- a/Source/graph/gremlinEndpoints.ts +++ b/Source/graph/gremlinEndpoints.ts @@ -3,35 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { nonNullValue } from '../utils/nonNull'; -import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { nonNullValue } from "../utils/nonNull"; +import { IGremlinEndpoint } from "../vscode-cosmosdbgraph.api"; -export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise { - // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk - const response = await client.databaseAccounts.get(resourceGroup, account); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const endpointUri = response.documentEndpoint; - // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint - return endpointUri ? parseEndpointUrl(endpointUri) : undefined; +export async function tryGetGremlinEndpointFromAzure( + client: CosmosDBManagementClient, + resourceGroup: string, + account: string +): Promise { + // Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk + const response = await client.databaseAccounts.get(resourceGroup, account); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const endpointUri = response.documentEndpoint; + // If it doesn't have gremlinEndpoint in its properties, it must be a pre-GA endpoint + return endpointUri ? parseEndpointUrl(endpointUri) : undefined; } -export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinEndpoint[] { - // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ +export function getPossibleGremlinEndpoints( + documentEndpoint: string +): IGremlinEndpoint[] { + // E.g., given a document endpoint from Azure such as https://.documents.azure.com:443/ - const documentSuffix = '.documents.azure.com'; - if (documentEndpoint.indexOf(documentSuffix) >= 0) { - // Pre-GA style (Dec 2017) - const preGAEndpoint = documentEndpoint.replace(documentSuffix, '.graphs.azure.com'); + const documentSuffix = ".documents.azure.com"; + if (documentEndpoint.indexOf(documentSuffix) >= 0) { + // Pre-GA style (Dec 2017) + const preGAEndpoint = documentEndpoint.replace( + documentSuffix, + ".graphs.azure.com" + ); - // Post-GA style (Dec 2017) - const postGAEndpoint = documentEndpoint.replace(documentSuffix, '.gremlin.cosmosdb.azure.com'); + // Post-GA style (Dec 2017) + const postGAEndpoint = documentEndpoint.replace( + documentSuffix, + ".gremlin.cosmosdb.azure.com" + ); - return [parseEndpointUrl(postGAEndpoint), parseEndpointUrl(preGAEndpoint)]; - } else { - console.warn(`Unexpected document URL format: ${documentEndpoint}`); - return [parseEndpointUrl(documentEndpoint)]; - } + return [ + parseEndpointUrl(postGAEndpoint), + parseEndpointUrl(preGAEndpoint), + ]; + } else { + console.warn(`Unexpected document URL format: ${documentEndpoint}`); + return [parseEndpointUrl(documentEndpoint)]; + } } /** @@ -39,9 +54,12 @@ export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinE * @param url An account URL such as 'https://.documents.azure.com:443/' */ function parseEndpointUrl(url: string): IGremlinEndpoint { - const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch'); - console.assert(!!protocol && !!host, "Unexpected endpoint format"); - const port = parseInt(portString || "443", 10); - console.assert(port > 0, "Unexpected port"); - return { host, port, ssl: protocol.toLowerCase() === "https" }; + const [, protocol, host, , portString] = nonNullValue( + url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), + "urlMatch" + ); + console.assert(!!protocol && !!host, "Unexpected endpoint format"); + const port = parseInt(portString || "443", 10); + console.assert(port > 0, "Unexpected port"); + return { host, port, ssl: protocol.toLowerCase() === "https" }; } diff --git a/Source/graph/registerGraphCommands.ts b/Source/graph/registerGraphCommands.ts index 1746c638b..21e05d9a5 100644 --- a/Source/graph/registerGraphCommands.ts +++ b/Source/graph/registerGraphCommands.ts @@ -3,60 +3,97 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; -import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants'; -import { ext } from '../extensionVariables'; +import { + AzExtTreeItem, + IActionContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; +import { cosmosGremlinFilter, doubleClickDebounceDelay } from "../constants"; +import { ext } from "../extensionVariables"; import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem"; import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem"; import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem"; import { GraphTreeItem } from "./tree/GraphTreeItem"; export function registerGraphCommands(): void { - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickGraph(context, GraphCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => { - if (!node) { - node = await pickGraph(context, GraphTreeItem.contextValue); - } - await node.showExplorer(context); - }, doubleClickDebounceDelay); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createGraphDatabase", + createGraphDatabase + ); + registerCommandWithTreeNodeUnwrapping("cosmosDB.createGraph", createGraph); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteGraphDatabase", + async (context: IActionContext, node?: GraphDatabaseTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph( + context, + GraphDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteGraph", + async (context: IActionContext, node?: GraphCollectionTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickGraph( + context, + GraphCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openGraphExplorer", + async (context: IActionContext, node: GraphTreeItem) => { + if (!node) { + node = await pickGraph( + context, + GraphTreeItem.contextValue + ); + } + await node.showExplorer(context); + }, + doubleClickDebounceDelay + ); } -export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise { - if (!node) { - node = await pickGraph(context); - } - await node.createChild(context); +export async function createGraphDatabase( + context: IActionContext, + node?: GraphAccountTreeItem +): Promise { + if (!node) { + node = await pickGraph(context); + } + await node.createChild(context); } -export async function createGraph(context: IActionContext, node?: GraphDatabaseTreeItem): Promise { - if (!node) { - node = await pickGraph(context, GraphDatabaseTreeItem.contextValue); - } - await node.createChild(context); +export async function createGraph( + context: IActionContext, + node?: GraphDatabaseTreeItem +): Promise { + if (!node) { + node = await pickGraph( + context, + GraphDatabaseTreeItem.contextValue + ); + } + await node.createChild(context); } -async function pickGraph(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosGremlinFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickGraph( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [cosmosGremlinFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/graph/tree/GraphAccountTreeItem.ts b/Source/graph/tree/GraphAccountTreeItem.ts index 7e1f561fa..8025e4f8e 100644 --- a/Source/graph/tree/GraphAccountTreeItem.ts +++ b/Source/graph/tree/GraphAccountTreeItem.ts @@ -3,43 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { DatabaseDefinition, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils'; -import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { DatabaseDefinition, Resource } from "@azure/cosmos"; +import { AzExtParentTreeItem } from "@microsoft/vscode-azext-utils"; +import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; +import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; +import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; +import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; +import { GraphTreeItem } from "./GraphTreeItem"; export class GraphAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBGraphAccount"; - public contextValue: string = GraphAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBGraphAccount"; + public contextValue: string = GraphAccountTreeItem.contextValue; - constructor(parent: AzExtParentTreeItem, id: string, label: string, documentEndpoint: string, private _gremlinEndpoint: IGremlinEndpoint | undefined, masterKey: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent, id, label, documentEndpoint, masterKey, isEmulator, databaseAccount); - this.valuesToMask.push(documentEndpoint); - if (_gremlinEndpoint) { - this.valuesToMask.push(_gremlinEndpoint.host); - } - } + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + documentEndpoint: string, + private _gremlinEndpoint: IGremlinEndpoint | undefined, + masterKey: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super( + parent, + id, + label, + documentEndpoint, + masterKey, + isEmulator, + databaseAccount + ); + this.valuesToMask.push(documentEndpoint); + if (_gremlinEndpoint) { + this.valuesToMask.push(_gremlinEndpoint.host); + } + } - public initChild(database: DatabaseDefinition & Resource): GraphDatabaseTreeItem { - return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); - } + public initChild( + database: DatabaseDefinition & Resource + ): GraphDatabaseTreeItem { + return new GraphDatabaseTreeItem(this, this._gremlinEndpoint, database); + } - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case GraphDatabaseTreeItem.contextValue: - case GraphCollectionTreeItem.contextValue: - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - case GraphTreeItem.contextValue: - return true; - default: - return false; - } - } + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case GraphDatabaseTreeItem.contextValue: + case GraphCollectionTreeItem.contextValue: + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + case GraphTreeItem.contextValue: + return true; + default: + return false; + } + } } diff --git a/Source/graph/tree/GraphCollectionTreeItem.ts b/Source/graph/tree/GraphCollectionTreeItem.ts index 63709d977..efc25ae4c 100644 --- a/Source/graph/tree/GraphCollectionTreeItem.ts +++ b/Source/graph/tree/GraphCollectionTreeItem.ts @@ -3,85 +3,108 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos'; -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem'; -import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem'; -import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot'; -import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem'; -import { GraphTreeItem } from './GraphTreeItem'; +import { + Container, + ContainerDefinition, + CosmosClient, + Resource, +} from "@azure/cosmos"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { DocDBStoredProceduresTreeItem } from "../../docdb/tree/DocDBStoredProceduresTreeItem"; +import { DocDBStoredProcedureTreeItem } from "../../docdb/tree/DocDBStoredProcedureTreeItem"; +import { IDocDBTreeRoot } from "../../docdb/tree/IDocDBTreeRoot"; +import { GraphDatabaseTreeItem } from "./GraphDatabaseTreeItem"; +import { GraphTreeItem } from "./GraphTreeItem"; export class GraphCollectionTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBGraph"; - public readonly contextValue: string = GraphCollectionTreeItem.contextValue; - public readonly parent: GraphDatabaseTreeItem; - - private readonly _graphTreeItem: GraphTreeItem; - private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphDatabaseTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this._collection = collection; - this._graphTreeItem = new GraphTreeItem(this, this._collection); - this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem(this); - } - - public get root(): IDocDBTreeRoot { - return this.parent.root; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return this._collection.id; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - return [this._graphTreeItem, this._storedProceduresTreeItem]; - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse); - const client = this.root.getCosmosClient(); - await this.getContainerClient(client).delete(); - } - - public pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): AzExtTreeItem | undefined { - for (const expectedContextValue of expectedContextValues) { - switch (expectedContextValue) { - case GraphTreeItem.contextValue: - return this._graphTreeItem; - case DocDBStoredProceduresTreeItem.contextValue: - case DocDBStoredProcedureTreeItem.contextValue: - return this._storedProceduresTreeItem; - - default: - } - } - - return undefined; - } - - public getContainerClient(client: CosmosClient): Container { - return (this.parent.getDatabaseClient(client)).container(this.id); - - } + public static contextValue: string = "cosmosDBGraph"; + public readonly contextValue: string = GraphCollectionTreeItem.contextValue; + public readonly parent: GraphDatabaseTreeItem; + + private readonly _graphTreeItem: GraphTreeItem; + private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem; + + private readonly _collection: ContainerDefinition & Resource; + + constructor( + parent: GraphDatabaseTreeItem, + collection: ContainerDefinition & Resource + ) { + super(parent); + this._collection = collection; + this._graphTreeItem = new GraphTreeItem(this, this._collection); + this._storedProceduresTreeItem = new DocDBStoredProceduresTreeItem( + this + ); + } + + public get root(): IDocDBTreeRoot { + return this.parent.root; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return this._collection.id; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return [this._graphTreeItem, this._storedProceduresTreeItem]; + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteGraphCollection" }, + DialogResponses.deleteResponse + ); + const client = this.root.getCosmosClient(); + await this.getContainerClient(client).delete(); + } + + public pickTreeItemImpl( + expectedContextValues: (string | RegExp)[] + ): AzExtTreeItem | undefined { + for (const expectedContextValue of expectedContextValues) { + switch (expectedContextValue) { + case GraphTreeItem.contextValue: + return this._graphTreeItem; + case DocDBStoredProceduresTreeItem.contextValue: + case DocDBStoredProcedureTreeItem.contextValue: + return this._storedProceduresTreeItem; + + default: + } + } + + return undefined; + } + + public getContainerClient(client: CosmosClient): Container { + return this.parent.getDatabaseClient(client).container(this.id); + } } diff --git a/Source/graph/tree/GraphDatabaseTreeItem.ts b/Source/graph/tree/GraphDatabaseTreeItem.ts index 1c5332700..4fc7a9655 100644 --- a/Source/graph/tree/GraphDatabaseTreeItem.ts +++ b/Source/graph/tree/GraphDatabaseTreeItem.ts @@ -3,63 +3,76 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase'; -import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api'; -import { getPossibleGremlinEndpoints } from '../gremlinEndpoints'; -import { GraphAccountTreeItem } from './GraphAccountTreeItem'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { + ContainerDefinition, + CosmosClient, + Database, + DatabaseDefinition, + Resource, +} from "@azure/cosmos"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { DocDBDatabaseTreeItemBase } from "../../docdb/tree/DocDBDatabaseTreeItemBase"; +import { IGremlinEndpoint } from "../../vscode-cosmosdbgraph.api"; +import { getPossibleGremlinEndpoints } from "../gremlinEndpoints"; +import { GraphAccountTreeItem } from "./GraphAccountTreeItem"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase { - public static contextValue: string = "cosmosDBGraphDatabase"; - public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = 'Graph'; + public static contextValue: string = "cosmosDBGraphDatabase"; + public readonly contextValue: string = GraphDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Graph"; - constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) { - super(parent, database); - } + constructor( + parent: GraphAccountTreeItem, + private _gremlinEndpoint: IGremlinEndpoint | undefined, + database: DatabaseDefinition & Resource + ) { + super(parent, database); + } - public initChild(collection: ContainerDefinition & Resource): GraphCollectionTreeItem { - return new GraphCollectionTreeItem(this, collection); - } + public initChild( + collection: ContainerDefinition & Resource + ): GraphCollectionTreeItem { + return new GraphCollectionTreeItem(this, collection); + } - // Gremlin endpoint, if definitely known - get gremlinEndpoint(): IGremlinEndpoint | undefined { - return this._gremlinEndpoint; - } + // Gremlin endpoint, if definitely known + get gremlinEndpoint(): IGremlinEndpoint | undefined { + return this._gremlinEndpoint; + } - get possibleGremlinEndpoints(): IGremlinEndpoint[] { - return getPossibleGremlinEndpoints(this.root.endpoint); - } + get possibleGremlinEndpoints(): IGremlinEndpoint[] { + return getPossibleGremlinEndpoints(this.root.endpoint); + } - public getDatabaseClient(client: CosmosClient): Database { - return client.database(this.id); + public getDatabaseClient(client: CosmosClient): Database { + return client.database(this.id); + } - } + protected override async getNewPartitionKey( + context: IActionContext + ): Promise { + let partitionKey: string | undefined = await context.ui.showInputBox({ + prompt: "Enter the partition key for the collection, or leave blank for fixed size.", + stepName: "partitionKeyForCollection", + validateInput: this.validatePartitionKey, + placeHolder: "e.g. /address", + }); - protected override async getNewPartitionKey(context: IActionContext): Promise { - let partitionKey: string | undefined = await context.ui.showInputBox({ - prompt: 'Enter the partition key for the collection, or leave blank for fixed size.', - stepName: 'partitionKeyForCollection', - validateInput: this.validatePartitionKey, - placeHolder: 'e.g. /address' - }); + if (partitionKey && partitionKey.length && partitionKey[0] !== "/") { + partitionKey = "/" + partitionKey; + } - if (partitionKey && partitionKey.length && partitionKey[0] !== '/') { - partitionKey = '/' + partitionKey; - } + return partitionKey; + } - return partitionKey; - } - - protected validatePartitionKey(key: string): string | undefined { - if (/[#?\\]/.test(key)) { - return "Cannot contain these characters: ?,#,\\, etc."; - } - if (/.+\//.test(key)) { - return "Cannot be a nested path"; - } - return undefined; - } + protected validatePartitionKey(key: string): string | undefined { + if (/[#?\\]/.test(key)) { + return "Cannot contain these characters: ?,#,\\, etc."; + } + if (/.+\//.test(key)) { + return "Cannot be a nested path"; + } + return undefined; + } } diff --git a/Source/graph/tree/GraphTreeItem.ts b/Source/graph/tree/GraphTreeItem.ts index 800fded5a..d98da8b6b 100644 --- a/Source/graph/tree/GraphTreeItem.ts +++ b/Source/graph/tree/GraphTreeItem.ts @@ -3,54 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerDefinition, Resource } from '@azure/cosmos'; -import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { GraphCollectionTreeItem } from './GraphCollectionTreeItem'; +import { ContainerDefinition, Resource } from "@azure/cosmos"; +import { + AzExtTreeItem, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { localize } from "../../utils/localize"; +import { openUrl } from "../../utils/openUrl"; +import { GraphCollectionTreeItem } from "./GraphCollectionTreeItem"; -const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools"; +const alternativeGraphVisualizationToolsDocLink = + "https://aka.ms/cosmosdb-graph-alternative-tools"; export class GraphTreeItem extends AzExtTreeItem { - public static contextValue: string = "cosmosDBGraphGraph"; - public readonly contextValue: string = GraphTreeItem.contextValue; - public readonly parent: GraphCollectionTreeItem; - public suppressMaskLabel = true; - - private readonly _collection: ContainerDefinition & Resource; - - constructor(parent: GraphCollectionTreeItem, collection: ContainerDefinition & Resource) { - super(parent); - this.commandId = 'cosmosDB.openGraphExplorer'; - this._collection = collection; - } - - public get id(): string { - return this._collection.id; - } - - public get label(): string { - return "Graph"; - } - - public get link(): string { - return this._collection._self; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public async showExplorer(_context: IActionContext): Promise { - const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.'); - const alternativeToolsOption = "Alternative Tools"; - const result = await vscode.window.showErrorMessage( - message, - alternativeToolsOption - ); - if (result === alternativeToolsOption) { - await openUrl(alternativeGraphVisualizationToolsDocLink); - } - } + public static contextValue: string = "cosmosDBGraphGraph"; + public readonly contextValue: string = GraphTreeItem.contextValue; + public readonly parent: GraphCollectionTreeItem; + public suppressMaskLabel = true; + + private readonly _collection: ContainerDefinition & Resource; + + constructor( + parent: GraphCollectionTreeItem, + collection: ContainerDefinition & Resource + ) { + super(parent); + this.commandId = "cosmosDB.openGraphExplorer"; + this._collection = collection; + } + + public get id(): string { + return this._collection.id; + } + + public get label(): string { + return "Graph"; + } + + public get link(): string { + return this._collection._self; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public async showExplorer(_context: IActionContext): Promise { + const message: string = localize( + "mustInstallGraph", + "Cosmos DB Graph extension has been retired." + ); + const alternativeToolsOption = "Alternative Tools"; + const result = await vscode.window.showErrorMessage( + message, + alternativeToolsOption + ); + if (result === alternativeToolsOption) { + await openUrl(alternativeGraphVisualizationToolsDocLink); + } + } } diff --git a/Source/mongo/MongoCommand.ts b/Source/mongo/MongoCommand.ts index 79c33731f..ea9466b45 100644 --- a/Source/mongo/MongoCommand.ts +++ b/Source/mongo/MongoCommand.ts @@ -3,22 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { RecognitionException } from 'antlr4ts'; -import * as vscode from 'vscode'; +import { RecognitionException } from "antlr4ts"; +import * as vscode from "vscode"; export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: Object[]; - errors?: ErrorDescription[]; - chained?: boolean; + range: vscode.Range; + text: string; + collection?: string; + name?: string; + arguments?: string[]; + argumentObjects?: Object[]; + errors?: ErrorDescription[]; + chained?: boolean; } export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; + range: vscode.Range; + message: string; + exception?: RecognitionException; } diff --git a/Source/mongo/MongoScrapbook.ts b/Source/mongo/MongoScrapbook.ts index d5dfe6d00..2f441285e 100644 --- a/Source/mongo/MongoScrapbook.ts +++ b/Source/mongo/MongoScrapbook.ts @@ -3,489 +3,718 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ObjectID } from 'bson'; -import { Collection } from 'mongodb'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { filterType, findType } from '../utils/array'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { mongoLexer } from './grammar/mongoLexer'; -import * as mongoParser from './grammar/mongoParser'; -import { MongoVisitor } from './grammar/visitors'; -import { ErrorDescription, MongoCommand } from './MongoCommand'; -import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem'; -import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem'; +import { + IActionContext, + IParsedError, + openReadOnlyContent, + parseError, + ReadOnlyContent, +} from "@microsoft/vscode-azext-utils"; +import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; +import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { ObjectID } from "bson"; +import { Collection } from "mongodb"; +import { EOL } from "os"; +import * as vscode from "vscode"; +import { ext } from "../extensionVariables"; +import { filterType, findType } from "../utils/array"; +import { localize } from "../utils/localize"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { LexerErrorListener, ParserErrorListener } from "./errorListeners"; +import { mongoLexer } from "./grammar/mongoLexer"; +import * as mongoParser from "./grammar/mongoParser"; +import { MongoVisitor } from "./grammar/visitors"; +import { ErrorDescription, MongoCommand } from "./MongoCommand"; +import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; +import { + MongoDatabaseTreeItem, + stripQuotes, +} from "./tree/MongoDatabaseTreeItem"; +import { + IMongoDocument, + MongoDocumentTreeItem, +} from "./tree/MongoDocumentTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); -const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromTextDocument(document); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of (command.errors || [])) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; +const notInScrapbookMessage = + "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command."; + +export function getAllErrorsFromTextDocument( + document: vscode.TextDocument +): vscode.Diagnostic[] { + const commands = getAllCommandsFromTextDocument(document); + const errors: vscode.Diagnostic[] = []; + for (const command of commands) { + for (const error of command.errors || []) { + const diagnostic = new vscode.Diagnostic( + error.range, + error.message + ); + errors.push(diagnostic); + } + } + + return errors; } -export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise { - ext.outputChannel.appendLog("Executing all commands in scrapbook..."); - const commands = getAllCommandsFromActiveEditor(); - await executeCommands(context, commands); +export async function executeAllCommandsFromActiveEditor( + context: IActionContext +): Promise { + ext.outputChannel.appendLog("Executing all commands in scrapbook..."); + const commands = getAllCommandsFromActiveEditor(); + await executeCommands(context, commands); } -export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise { - const commands = getAllCommandsFromActiveEditor(); - const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start); - return await executeCommand(context, command); +export async function executeCommandFromActiveEditor( + context: IActionContext, + position?: vscode.Position +): Promise { + const commands = getAllCommandsFromActiveEditor(); + const command = findCommandAtPosition( + commands, + position || vscode.window.activeTextEditor?.selection.start + ); + return await executeCommand(context, command); } function getAllCommandsFromActiveEditor(): MongoCommand[] { - const activeEditor = vscode.window.activeTextEditor; - if (activeEditor) { - return getAllCommandsFromTextDocument(activeEditor.document); - } else { - // Shouldn't be able to reach this - throw new Error(notInScrapbookMessage); - } + const activeEditor = vscode.window.activeTextEditor; + if (activeEditor) { + return getAllCommandsFromTextDocument(activeEditor.document); + } else { + // Shouldn't be able to reach this + throw new Error(notInScrapbookMessage); + } } -export function getAllCommandsFromTextDocument(document: vscode.TextDocument): MongoCommand[] { - return getAllCommandsFromText(document.getText()); +export function getAllCommandsFromTextDocument( + document: vscode.TextDocument +): MongoCommand[] { + return getAllCommandsFromText(document.getText()); } -async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise { - const label: string = 'Scrapbook-execute-all-results'; - const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; - const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside }); - - for (const command of commands) { - try { - await executeCommand(context, command, readOnlyContent); - } catch (e) { - const err = parseError(e); - if (err.isUserCancelledError) { - throw e; - } else { - const message = `${command.text.split('(')[0]} at ${command.range.start.line + 1}:${command.range.start.character + 1}: ${err.message}`; - throw new Error(message); - } - } - } +async function executeCommands( + context: IActionContext, + commands: MongoCommand[] +): Promise { + const label: string = "Scrapbook-execute-all-results"; + const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`; + const readOnlyContent: ReadOnlyContent = await openReadOnlyContent( + { label, fullId }, + "", + ".txt", + { viewColumn: vscode.ViewColumn.Beside } + ); + + for (const command of commands) { + try { + await executeCommand(context, command, readOnlyContent); + } catch (e) { + const err = parseError(e); + if (err.isUserCancelledError) { + throw e; + } else { + const message = `${command.text.split("(")[0]} at ${ + command.range.start.line + 1 + }:${command.range.start.character + 1}: ${err.message}`; + throw new Error(message); + } + } + } } -async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise { - if (command) { - try { - context.telemetry.properties.command = command.name; - context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0); - } catch (error) { - // Ignore - } - - const database = ext.connectedMongoDB; - if (!database) { - throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item'); - } - if (command.errors && command.errors.length > 0) { - //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. - const err = command.errors[0]; - throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`)); - } - - // we don't handle chained commands so we can only handle "find" if isn't chained - if (command.name === 'find' && !command.chained) { - const db = await database.connectToDb(); - const collectionName: string = nonNullProp(command, 'collection'); - const collection: Collection = db.collection(collectionName); - // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because - // the executed 'find' command could have a filter or projection that is not handled by a cached tree node - const node = new MongoCollectionTreeItem(database, collection, command.argumentObjects); - await ext.fileSystem.showTextDocument(node, { viewColumn: vscode.ViewColumn.Beside }); - } else { - const result = await database.executeCommand(command, context); - if (command.name === 'findOne') { - if (result === "null") { - throw new Error(`Could not find any documents`); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - const document: IMongoDocument = EJSON.parse(result); - const collectionName: string = nonNullProp(command, 'collection'); - - const collectionId: string = `${database.fullId}/${collectionName}`; - const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context); - if (!colNode) { - throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName)); - } - const docNode = new MongoDocumentTreeItem(colNode, document); - await ext.fileSystem.showTextDocument(docNode, { viewColumn: vscode.ViewColumn.Beside }); - } else { - if (readOnlyContent) { - await readOnlyContent.append(`${result}${EOL}${EOL}`); - } else { - const label: string = 'Scrapbook-results'; - const fullId: string = `${database.fullId}/${label}`; - await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside }); - } - - await refreshTreeAfterCommand(database, command, context); - } - } - } else { - throw new Error('No MongoDB command found at the current cursor location.'); - } +async function executeCommand( + context: IActionContext, + command: MongoCommand, + readOnlyContent?: ReadOnlyContent +): Promise { + if (command) { + try { + context.telemetry.properties.command = command.name; + context.telemetry.properties.argsCount = String( + command.arguments ? command.arguments.length : 0 + ); + } catch (error) { + // Ignore + } + + const database = ext.connectedMongoDB; + if (!database) { + throw new Error( + 'Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item' + ); + } + if (command.errors && command.errors.length > 0) { + //Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom. + const err = command.errors[0]; + throw new Error( + localize( + "unableToParseSyntax", + `Unable to parse syntax. Error near line ${ + err.range.start.line + 1 + }, column ${err.range.start.character + 1}: "${ + err.message + }"` + ) + ); + } + + // we don't handle chained commands so we can only handle "find" if isn't chained + if (command.name === "find" && !command.chained) { + const db = await database.connectToDb(); + const collectionName: string = nonNullProp(command, "collection"); + const collection: Collection = db.collection(collectionName); + // NOTE: Intentionally creating a _new_ tree item rather than searching for a cached node in the tree because + // the executed 'find' command could have a filter or projection that is not handled by a cached tree node + const node = new MongoCollectionTreeItem( + database, + collection, + command.argumentObjects + ); + await ext.fileSystem.showTextDocument(node, { + viewColumn: vscode.ViewColumn.Beside, + }); + } else { + const result = await database.executeCommand(command, context); + if (command.name === "findOne") { + if (result === "null") { + throw new Error(`Could not find any documents`); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const document: IMongoDocument = EJSON.parse(result); + const collectionName: string = nonNullProp( + command, + "collection" + ); + + const collectionId: string = `${database.fullId}/${collectionName}`; + const colNode: MongoCollectionTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + collectionId, + context + ); + if (!colNode) { + throw new Error( + localize( + "failedToFind", + 'Failed to find collection "{0}".', + collectionName + ) + ); + } + const docNode = new MongoDocumentTreeItem(colNode, document); + await ext.fileSystem.showTextDocument(docNode, { + viewColumn: vscode.ViewColumn.Beside, + }); + } else { + if (readOnlyContent) { + await readOnlyContent.append(`${result}${EOL}${EOL}`); + } else { + const label: string = "Scrapbook-results"; + const fullId: string = `${database.fullId}/${label}`; + await openReadOnlyContent( + { label, fullId }, + result, + ".json", + { viewColumn: vscode.ViewColumn.Beside } + ); + } + + await refreshTreeAfterCommand(database, command, context); + } + } + } else { + throw new Error( + "No MongoDB command found at the current cursor location." + ); + } } -async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise { - if (command.name === 'drop') { - await database.refresh(context); - } else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) { - const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context); - if (collectionNode) { - await collectionNode.refresh(context); - } - } +async function refreshTreeAfterCommand( + database: MongoDatabaseTreeItem, + command: MongoCommand, + context: IActionContext +): Promise { + if (command.name === "drop") { + await database.refresh(context); + } else if ( + command.collection && + command.name && + /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test( + command.name + ) + ) { + const collectionNode = await ext.rgApi.appResourceTree.findTreeItem( + database.fullId + "/" + command.collection, + context + ); + if (collectionNode) { + await collectionNode.refresh(context); + } + } } export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: "" - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; + const lexer = new mongoLexer(new InputStream(content)); + const lexerListener = new LexerErrorListener(); + lexer.removeErrorListeners(); // Default listener outputs to the console + lexer.addErrorListener(lexerListener); + const tokens: CommonTokenStream = new CommonTokenStream(lexer); + + const parser = new mongoParser.mongoParser(tokens); + const parserListener = new ParserErrorListener(); + parser.removeErrorListeners(); // Default listener outputs to the console + parser.addErrorListener(parserListener); + + const commandsContext: mongoParser.MongoCommandsContext = + parser.mongoCommands(); + const commands = new FindMongoCommandsVisitor().visit(commandsContext); + + // Match errors with commands based on location + const errors = lexerListener.errors.concat(parserListener.errors); + errors.sort((a, b) => { + const linediff = a.range.start.line - b.range.start.line; + const chardiff = a.range.start.character - b.range.start.character; + return linediff || chardiff; + }); + for (const err of errors) { + const associatedCommand = findCommandAtPosition( + commands, + err.range.start + ); + if (associatedCommand) { + associatedCommand.errors = associatedCommand.errors || []; + associatedCommand.errors.push(err); + } else { + // Create a new command to hook this up to + const emptyCommand: MongoCommand = { + collection: undefined, + name: undefined, + range: err.range, + text: "", + }; + emptyCommand.errors = [err]; + commands.push(emptyCommand); + } + } + + return commands; } -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; +export function findCommandAtPosition( + commands: MongoCommand[], + position?: vscode.Position +): MongoCommand { + let lastCommandOnSameLine: MongoCommand | undefined; + let lastCommandBeforePosition: MongoCommand | undefined; + if (position) { + for (const command of commands) { + if (command.range.contains(position)) { + return command; + } + if (command.range.end.line === position.line) { + lastCommandOnSameLine = command; + } + if (command.range.end.isBefore(position)) { + lastCommandBeforePosition = command; + } + } + } + return ( + lastCommandOnSameLine || + lastCommandBeforePosition || + commands[commands.length - 1] + ); } class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop'); - this.commands.push({ - range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp(lastCommand, 'argumentObjects').push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand(`Unrecognized node type encountered. We could not parse ${child.text}`, ctx); - return {}; - } - } - - private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(`Unrecognized token. Token text: ${text}`, ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { // Argument is {} - return {}; - } else { - const parsedObject: Object = {}; - const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children'); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall'); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken'); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')' - this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext); - if (argumentContextArray.length > 1) { - this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx); - return {}; - } - } - - private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} { - const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} { - if (!tokenText) { // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object { - let hexID: string; - let constructedObject: ObjectID; - if (!tokenText) { // usage : ObjectID() - constructedObject = new ObjectID(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectID(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ""; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - let tokenObject = new RegExp(pattern, flags); - // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars - tokenObject = tokenObject; - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop'); - const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* + private commands: MongoCommand[] = []; + + public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { + const funcCallCount: number = filterType( + ctx.children, + mongoParser.FunctionCallContext + ).length; + const stop = nonNullProp(ctx, "stop"); + this.commands.push({ + range: new vscode.Range( + ctx.start.line - 1, + ctx.start.charPositionInLine, + stop.line - 1, + stop.charPositionInLine + ), + text: ctx.text, + name: "", + arguments: [], + argumentObjects: [], + chained: funcCallCount > 1 ? true : false, + }); + return super.visitCommand(ctx); + } + + public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { + this.commands[this.commands.length - 1].collection = ctx.text; + return super.visitCollection(ctx); + } + + public visitFunctionCall( + ctx: mongoParser.FunctionCallContext + ): MongoCommand[] { + if (ctx.parent instanceof mongoParser.CommandContext) { + this.commands[this.commands.length - 1].name = + (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ""; + } + return super.visitFunctionCall(ctx); + } + + public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { + try { + const argumentsContext = ctx.parent; + if (argumentsContext) { + const functionCallContext = argumentsContext.parent; + if ( + functionCallContext && + functionCallContext.parent instanceof + mongoParser.CommandContext + ) { + const lastCommand = this.commands[this.commands.length - 1]; + const argAsObject = this.contextToObject(ctx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const argText = EJSON.stringify(argAsObject); + nonNullProp(lastCommand, "arguments").push(argText); + const escapeHandled = + this.deduplicateEscapesForRegex(argText); + let ejsonParsed = {}; + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + ejsonParsed = EJSON.parse(escapeHandled); + } catch (error) { + //EJSON parse failed due to a wrong flag, etc. + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + nonNullProp(lastCommand, "argumentObjects").push( + ejsonParsed + ); + } + } + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + } + return super.visitArgument(ctx); + } + + protected defaultResult(_node: ParseTree): MongoCommand[] { + return this.commands; + } + + private contextToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + if (!ctx || ctx.childCount === 0) { + //Base case and malformed statements + return {}; + } + // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 + const child: ParseTree = nonNullProp(ctx, "children")[0]; + if (child instanceof mongoParser.LiteralContext) { + return this.literalContextToObject(child, ctx); + } else if (child instanceof mongoParser.ObjectLiteralContext) { + return this.objectLiteralContextToObject(child); + } else if (child instanceof mongoParser.ArrayLiteralContext) { + return this.arrayLiteralContextToObject(child); + } else if (child instanceof mongoParser.FunctionCallContext) { + return this.functionCallContextToObject(child, ctx); + } else if (child instanceof ErrorNode) { + return {}; + } else { + this.addErrorToCommand( + `Unrecognized node type encountered. We could not parse ${child.text}`, + ctx + ); + return {}; + } + } + + private literalContextToObject( + child: mongoParser.LiteralContext, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + const text = child.text; + const tokenType = child.start.type; + const nonStringLiterals = [ + mongoParser.mongoParser.NullLiteral, + mongoParser.mongoParser.BooleanLiteral, + mongoParser.mongoParser.NumericLiteral, + ]; + if (tokenType === mongoParser.mongoParser.StringLiteral) { + return stripQuotes(text); + } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { + return this.regexLiteralContextToObject(ctx, text); + } else if (nonStringLiterals.indexOf(tokenType) > -1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return JSON.parse(text); + } else { + this.addErrorToCommand( + `Unrecognized token. Token text: ${text}`, + ctx + ); + return {}; + } + } + + private objectLiteralContextToObject( + child: mongoParser.ObjectLiteralContext + ): Object { + const propertyNameAndValue = findType( + child.children, + mongoParser.PropertyNameAndValueListContext + ); + if (!propertyNameAndValue) { + // Argument is {} + return {}; + } else { + const parsedObject: Object = {}; + const propertyAssignments = filterType( + propertyNameAndValue.children, + mongoParser.PropertyAssignmentContext + ); + for (const propertyAssignment of propertyAssignments) { + const propertyAssignmentChildren = nonNullProp( + propertyAssignment, + "children" + ); + const propertyName = ( + propertyAssignmentChildren[0] + ); + const propertyValue = ( + propertyAssignmentChildren[2] + ); + parsedObject[stripQuotes(propertyName.text)] = + this.contextToObject(propertyValue); + } + return parsedObject; + } + } + + private arrayLiteralContextToObject( + child: mongoParser.ArrayLiteralContext + ) { + const elementList = findType( + child.children, + mongoParser.ElementListContext + ); + if (elementList) { + const elementItems = filterType( + elementList.children, + mongoParser.PropertyValueContext + ); + return elementItems.map(this.contextToObject.bind(this)); + } else { + return []; + } + } + + private functionCallContextToObject( + child: mongoParser.FunctionCallContext, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): Object { + const functionTokens = child.children; + const constructorCall: TerminalNode = nonNullValue( + findType(functionTokens, TerminalNode), + "constructorCall" + ); + const argumentsToken: mongoParser.ArgumentsContext = nonNullValue( + findType(functionTokens, mongoParser.ArgumentsContext), + "argumentsToken" + ); + if ( + !( + argumentsToken._CLOSED_PARENTHESIS && + argumentsToken._OPEN_PARENTHESIS + ) + ) { + //argumentsToken does not have '(' or ')' + this.addErrorToCommand( + `Expecting parentheses or quotes at '${constructorCall.text}'`, + ctx + ); + return {}; + } + + const argumentContextArray: mongoParser.ArgumentContext[] = filterType( + argumentsToken.children, + mongoParser.ArgumentContext + ); + if (argumentContextArray.length > 1) { + this.addErrorToCommand( + `Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, + ctx + ); + return {}; + } + + const tokenText: string | undefined = argumentContextArray.length + ? argumentContextArray[0].text + : undefined; + switch (constructorCall.text) { + case "ObjectId": + return this.objectIdToObject(ctx, tokenText); + case "ISODate": + return this.isodateToObject(ctx, tokenText); + case "Date": + return this.dateToObject(ctx, tokenText); + default: + this.addErrorToCommand( + `Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, + ctx + ); + return {}; + } + } + + private dateToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText); + if (date instanceof Date) { + return { $date: date.toString() }; + } else { + return date; + } + } + + private isodateToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): { $date: string } | {} { + const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true); + + if (date instanceof Date) { + return { $date: date.toISOString() }; + } else { + return date; + } + } + + private tryToConstructDate( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string, + isIsodate: boolean = false + ): Date | {} { + if (!tokenText) { + // usage : ObjectID() + return new Date(); + } else { + try { + tokenText = stripQuotes(tokenText); + + // if the tokenText was an isodate, the last char must be Z + if (isIsodate) { + if (tokenText[tokenText.length - 1] !== "Z") { + tokenText += "Z"; + } + } + + return new Date(tokenText); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + } + + private objectIdToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + tokenText?: string + ): Object { + let hexID: string; + let constructedObject: ObjectID; + if (!tokenText) { + // usage : ObjectID() + constructedObject = new ObjectID(); + } else { + hexID = stripQuotes(tokenText); + try { + constructedObject = new ObjectID(hexID); + } catch (error) { + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + return { $oid: constructedObject.toString() }; + } + + private regexLiteralContextToObject( + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, + text: string + ): Object { + const separator = text.lastIndexOf("/"); + const flags = + separator !== text.length - 1 ? text.substring(separator + 1) : ""; + const pattern = text.substring(1, separator); + try { + // validate the pattern and flags. + // It is intended for the errors thrown here to be handled by the catch block. + let tokenObject = new RegExp(pattern, flags); + // eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars + tokenObject = tokenObject; + // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax + return { + $regex: this.regexToStringNotation(pattern), + $options: flags, + }; + } catch (error) { + //User may not have finished typing + const parsedError: IParsedError = parseError(error); + this.addErrorToCommand(parsedError.message, ctx); + return {}; + } + } + + private addErrorToCommand( + errorMessage: string, + ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext + ): void { + const command = this.commands[this.commands.length - 1]; + command.errors = command.errors || []; + const stop = nonNullProp(ctx, "stop"); + const currentErrorDesc: ErrorDescription = { + message: errorMessage, + range: new vscode.Range( + ctx.start.line - 1, + ctx.start.charPositionInLine, + stop.line - 1, + stop.charPositionInLine + ), + }; + command.errors.push(currentErrorDesc); + } + + private regexToStringNotation(pattern: string): string { + // The equivalence: + // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" + return pattern.replace(/\\([0-9a-z.*])/i, "\\\\$1"); + } + + private deduplicateEscapesForRegex(argAsString: string): string { + const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; + /* We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. */ - return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); - } - + return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`); + } } diff --git a/Source/mongo/MongoShell.ts b/Source/mongo/MongoShell.ts index b8f982ee8..81784f2af 100644 --- a/Source/mongo/MongoShell.ts +++ b/Source/mongo/MongoShell.ts @@ -3,185 +3,216 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { InteractiveChildProcess } from '../utils/InteractiveChildProcess'; -import { randomUtils } from '../utils/randomUtils'; -import { getBatchSizeSetting } from '../utils/workspacUtils'; -import { wrapError } from '../utils/wrapError'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as os from "os"; +import * as vscode from "vscode"; +import { InteractiveChildProcess } from "../utils/InteractiveChildProcess"; +import { randomUtils } from "../utils/randomUtils"; +import { getBatchSizeSetting } from "../utils/workspacUtils"; +import { wrapError } from "../utils/wrapError"; -const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; +const timeoutMessage = + "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting."; const mongoShellMoreMessage = 'Type "it" for more'; -const extensionMoreMessage = '(More)'; +const extensionMoreMessage = "(More)"; -const sentinelBase = 'EXECUTION COMPLETED'; +const sentinelBase = "EXECUTION COMPLETED"; const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/; -function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; } +function createSentinel(): string { + return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; +} export class MongoShell extends vscode.Disposable { - - constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) { - super(() => this.dispose()); - } - - public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if (isEmulator) { - // Without these the connection will fail due to the self-signed DocDB certificate - if (args.indexOf("--ssl") < 0) { - args.push("--ssl"); - } - if (args.indexOf("--sslAllowInvalidCertificates") < 0) { - args.push("--sslAllowInvalidCertificates"); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '' - }); - const shell: MongoShell = new MongoShell(process, timeoutSeconds); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(""); - - // Configure the batch size - await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - script = convertToSingleLine(script); - - let stdOut = ""; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut(text => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage); - - resolve(stdOutNoSentinel); - } - })); - disposables.push( - this._process.onStdErr(text => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - reject(wrapCheckOutputWindow(text.trim())); - })); - disposables.push( - this._process.onError(error => { - reject(error); - })); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error("The process exited prematurely."); - } - - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } - finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } + constructor( + private _process: InteractiveChildProcess, + private _timeoutSeconds: number + ) { + super(() => this.dispose()); + } + + public static async create( + execPath: string, + execArgs: string[], + connectionString: string, + isEmulator: boolean | undefined, + outputChannel: vscode.OutputChannel, + timeoutSeconds: number + ): Promise { + try { + const args: string[] = execArgs.slice() || []; // Snapshot since we modify it + args.push(connectionString); + + if (isEmulator) { + // Without these the connection will fail due to the self-signed DocDB certificate + if (args.indexOf("--ssl") < 0) { + args.push("--ssl"); + } + if (args.indexOf("--sslAllowInvalidCertificates") < 0) { + args.push("--sslAllowInvalidCertificates"); + } + } + + const process: InteractiveChildProcess = + await InteractiveChildProcess.create({ + outputChannel: outputChannel, + command: execPath, + args, + outputFilterSearch: sentinelRegex, + outputFilterReplace: "", + }); + const shell: MongoShell = new MongoShell(process, timeoutSeconds); + + // Try writing an empty script to verify the process is running correctly and allow us + // to catch any errors related to the start-up of the process before trying to write to it. + await shell.executeScript(""); + + // Configure the batch size + await shell.executeScript( + `DBQuery.shellBatchSize = ${getBatchSizeSetting()}` + ); + + return shell; + } catch (error) { + throw wrapCheckOutputWindow(error); + } + } + + public dispose(): void { + this._process.kill(); + } + + public async useDatabase(database: string): Promise { + return await this.executeScript(`use ${database}`); + } + + public async executeScript(script: string): Promise { + script = convertToSingleLine(script); + + let stdOut = ""; + const sentinel = createSentinel(); + + const disposables: vscode.Disposable[] = []; + try { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + const result = await new Promise( + async (resolve, reject) => { + try { + startScriptTimeout(this._timeoutSeconds, reject); + + // Hook up events + disposables.push( + this._process.onStdOut((text) => { + stdOut += text; + // eslint-disable-next-line prefer-const + let { text: stdOutNoSentinel, removed } = + removeSentinel(stdOut, sentinel); + if (removed) { + // The sentinel was found, which means we are done. + + // Change the "type 'it' for more" message to one that doesn't ask users to type anything, + // since we're not currently interactive like that. + // CONSIDER: Ideally we would allow users to click a button to iterate through more data, + // or even just do it for them + stdOutNoSentinel = stdOutNoSentinel.replace( + mongoShellMoreMessage, + extensionMoreMessage + ); + + resolve(stdOutNoSentinel); + } + }) + ); + disposables.push( + this._process.onStdErr((text) => { + // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. + // So consider this an error. + // (It's okay if we fire this multiple times, the first one wins.) + reject(wrapCheckOutputWindow(text.trim())); + }) + ); + disposables.push( + this._process.onError((error) => { + reject(error); + }) + ); + + // Write the script to STDIN + if (script) { + this._process.writeLine(script); + } + + // Mark end of result by sending the sentinel wrapped in quotes so the console will spit + // it back out as a string value after it's done processing the script + const quotedSentinel = `"${sentinel}"`; + this._process.writeLine(quotedSentinel); // (Don't display the sentinel) + } catch (error) { + // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it + + if ((<{ code?: string }>error).code === "EPIPE") { + // Give a chance for start-up errors to show up before rejecting with this more general error message + await delay(500); + // eslint-disable-next-line no-ex-assign + error = new Error( + "The process exited prematurely." + ); + } + + reject(wrapCheckOutputWindow(error)); + } + } + ); + + return result.trim(); + } finally { + // Dispose event handlers + for (const d of disposables) { + d.dispose(); + } + } + } } -function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout( - () => { - reject(timeoutMessage); - }, - timeoutSeconds * 1000); - } +function startScriptTimeout( + timeoutSeconds: number | 0, + reject: (err: unknown) => void +): void { + if (timeoutSeconds > 0) { + setTimeout(() => { + reject(timeoutMessage); + }, timeoutSeconds * 1000); + } } function convertToSingleLine(script: string): string { - return script.split(os.EOL) - .map(line => line.trim()) - .join(''); - + return script + .split(os.EOL) + .map((line) => line.trim()) + .join(""); } -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } +function removeSentinel( + text: string, + sentinel: string +): { text: string; removed: boolean } { + const index = text.indexOf(sentinel); + if (index >= 0) { + return { text: text.slice(0, index), removed: true }; + } else { + return { text, removed: false }; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = "The output window may contain additional information."; - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); + const checkOutputMsg = + "The output window may contain additional information."; + return parseError(error).message.includes(checkOutputMsg) + ? error + : wrapError(error, checkOutputMsg); } diff --git a/Source/mongo/connectToMongoClient.ts b/Source/mongo/connectToMongoClient.ts index 88aa2df17..e2fe8d5d1 100644 --- a/Source/mongo/connectToMongoClient.ts +++ b/Source/mongo/connectToMongoClient.ts @@ -3,47 +3,58 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MongoClient, MongoClientOptions } from 'mongodb'; -import { emulatorPassword, Links } from '../constants'; - -export async function connectToMongoClient(connectionString: string, appName: string): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `@${appName}@`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true - }; - - if (isCosmosEmulatorConnectionString(connectionString)) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string, name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - throw error; - } +import { MongoClient, MongoClientOptions } from "mongodb"; +import { emulatorPassword, Links } from "../constants"; + +export async function connectToMongoClient( + connectionString: string, + appName: string +): Promise { + // appname appears to be the correct equivalent to user-agent for mongo + const options: MongoClientOptions = { + // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string + appName: `@${appName}@`, + // https://github.com/lmammino/mongo-uri-builder/issues/2 + useNewUrlParser: true, + useUnifiedTopology: true, + }; + + if (isCosmosEmulatorConnectionString(connectionString)) { + // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 + options.tlsAllowInvalidCertificates = true; + } + + try { + return await MongoClient.connect(connectionString, options); + } catch (err) { + // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info + const error = <{ message?: string; name?: string }>err; + const message = error && error.message; + + // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" + // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" + if ( + message && + /ECONNREFUSED/.test(message) && + /(localhost|127\.0\.0\.1)/.test(message) + ) { + throw new MongoConnectError(); + } + + throw error; + } } export class MongoConnectError extends Error { - constructor() { - super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`); - } + constructor() { + super( + `Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.` + ); + } } -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(emulatorPassword)); +export function isCosmosEmulatorConnectionString( + connectionString: string +): boolean { + return connectionString.includes(encodeURIComponent(emulatorPassword)); } diff --git a/Source/mongo/errorListeners.ts b/Source/mongo/errorListeners.ts index ea582d544..00d510cd5 100644 --- a/Source/mongo/errorListeners.ts +++ b/Source/mongo/errorListeners.ts @@ -3,65 +3,65 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { Recognizer } from 'antlr4ts/Recognizer'; -import { Token } from 'antlr4ts/Token'; +import { ANTLRErrorListener } from "antlr4ts/ANTLRErrorListener"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { Recognizer } from "antlr4ts/Recognizer"; +import { Token } from "antlr4ts/Token"; import * as vscode from "vscode"; -import { ErrorDescription } from './MongoCommand'; +import { ErrorDescription } from "./MongoCommand"; export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; + private _errors: ErrorDescription[] = []; - public get errors(): ErrorDescription[] { - return this._errors; - } + public get errors(): ErrorDescription[] { + return this._errors; + } - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: Token | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e, + }; + this._errors.push(error); + } } export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } + private _errors: ErrorDescription[] = []; - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined): void { + public get errors(): ErrorDescription[] { + return this._errors; + } - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); + public syntaxError( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _recognizer: Recognizer, + _offendingSymbol: number | undefined, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed + const range = new vscode.Range(position, position); - const error: ErrorDescription = { - message: msg, - range: range, - exception: e - }; - this._errors.push(error); - } + const error: ErrorDescription = { + message: msg, + range: range, + exception: e, + }; + this._errors.push(error); + } } diff --git a/Source/mongo/grammar/mongoLexer.ts b/Source/mongo/grammar/mongoLexer.ts index 3b6cbbdd0..47b461a6f 100644 --- a/Source/mongo/grammar/mongoLexer.ts +++ b/Source/mongo/grammar/mongoLexer.ts @@ -9,239 +9,312 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { RuleContext } from 'antlr4ts/RuleContext'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; +import { CharStream } from "antlr4ts/CharStream"; +import { NotNull, Override } from "antlr4ts/Decorators"; +import { Lexer } from "antlr4ts/Lexer"; +import * as Utils from "antlr4ts/misc/Utils"; +import { RuleContext } from "antlr4ts/RuleContext"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +export class mongoLexer extends Lexer { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly modeNames: string[] = ["DEFAULT_MODE"]; + public static readonly ruleNames: string[] = [ + "T__0", + "T__1", + "T__2", + "T__3", + "T__4", + "T__5", + "T__6", + "T__7", + "RegexLiteral", + "RegexFlag", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "STRING_ESCAPE", + "DecimalIntegerLiteral", + "ExponentPart", + "DecimalDigit", + "WHITESPACE", + ]; -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = [ - "DEFAULT_MODE" - ]; - - public static readonly ruleNames: string[] = [ - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral", - "RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral", - "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator", - "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral", - "ExponentPart", "DecimalDigit", "WHITESPACE" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoLexer.ruleNames; } - - @Override - public get serializedATN(): string { return mongoLexer._serializedATN; } - - @Override - public get modeNames(): string[] { return mongoLexer.modeNames; } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text) - ; - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + - "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + - "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + - "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + - "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + - "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + - "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + - "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + - "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + - "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + - "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + - "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + - "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + - "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + - "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" + - "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + - "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + - "kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" + - "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + - "Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" + - "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + - "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + - "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + - "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + - "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + - "\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + - ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + - "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + - "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + - "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + - "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" + - "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + - "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + - "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + - "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + - "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + - "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + - "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + - "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + - "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + - "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + - "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + - "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + - "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + - "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + - "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + - "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + - "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + - "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + - "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + - "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + - "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + - "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + - "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + - "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + - "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + - "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + - "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + - "\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" + - "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + - "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + - "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + - "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + - "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + - "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + - "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + - "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + - "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + - "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + - "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + - "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + - "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + - "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + - "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + - "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + - "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + - "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + - "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + - "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + - "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + - "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + - "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + - "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + - "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + - "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + - "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + - "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + - "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + - "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + - "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + - "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + - "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + - "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + - "\x04\x02\x03\x02\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, + "'('", + "','", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "':'", + undefined, + undefined, + undefined, + undefined, + "'null'", + undefined, + undefined, + undefined, + undefined, + "';'", + "'.'", + "'db'", + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + "RegexLiteral", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "WHITESPACE", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( + mongoLexer._LITERAL_NAMES, + mongoLexer._SYMBOLIC_NAMES, + [] + ); -} + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoLexer.VOCABULARY; + } + + private isExternalIdentifierText(text) { + return text === "db"; + } + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(mongoLexer._ATN, this); + } + + @Override + public get grammarFileName(): string { + return "mongo.g4"; + } + @Override + public get ruleNames(): string[] { + return mongoLexer.ruleNames; + } + + @Override + public get serializedATN(): string { + return mongoLexer._serializedATN; + } + + @Override + public get modeNames(): string[] { + return mongoLexer.modeNames; + } + + @Override + public sempred( + _localctx: RuleContext, + ruleIndex: number, + predIndex: number + ): boolean { + switch (ruleIndex) { + case 21: + return this.IDENTIFIER_sempred(_localctx, predIndex); + } + return true; + } + private IDENTIFIER_sempred( + _localctx: RuleContext, + predIndex: number + ): boolean { + switch (predIndex) { + case 0: + return !this.isExternalIdentifierText(this.text); + } + return true; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" + + "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + + "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + + "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + + "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + + "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + + "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" + + "\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" + + "\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" + + "\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" + + "\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" + + "\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + + "\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" + + "\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" + + "\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" + + "\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" + + "\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" + + "\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" + + "\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" + + "\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" + + "\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" + + "\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" + + "\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" + + "\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" + + "\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" + + "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" + + "-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" + + "\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" + + 'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' + + "]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" + + 'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' + + "\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" + + "\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" + + "\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" + + "\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" + + "\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" + + "\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + + "\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" + + ";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" + + "\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" + + "I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" + + "\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" + + "\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" + + "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" + + "\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" + + "\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" + + "\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" + + "\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" + + "AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" + + "F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" + + "IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" + + "MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" + + "\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" + + "\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" + + "\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" + + "\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" + + "\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" + + "\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" + + "\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" + + "\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" + + "\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" + + "qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" + + "uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" + + "xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" + + "\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" + + "\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" + + "\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" + + "\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" + + "\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" + + "\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" + + "\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" + + "/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" + + '\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' + + "\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" + + "\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" + + "\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" + + "\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" + + "\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" + + "\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" + + "\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" + + "\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" + + "\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" + + "\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" + + "$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" + + "\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" + + "\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" + + "\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" + + "\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" + + "\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" + + "\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" + + "\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" + + "\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" + + "\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" + + "\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" + + "\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" + + "\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" + + "\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" + + "\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" + + "\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" + + "\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" + + "\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" + + "\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" + + "\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" + + "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" + + "\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" + + "\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" + + "\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" + + "\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" + + "\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" + + "\x04\x02\x03\x02\b\x02\x02"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoLexer.__ATN) { + mongoLexer.__ATN = new ATNDeserializer().deserialize( + Utils.toCharArray(mongoLexer._serializedATN) + ); + } + + return mongoLexer.__ATN; + } +} diff --git a/Source/mongo/grammar/mongoListener.ts b/Source/mongo/grammar/mongoListener.ts index 43514f500..d1d8ffac8 100644 --- a/Source/mongo/grammar/mongoListener.ts +++ b/Source/mongo/grammar/mongoListener.ts @@ -1,17 +1,30 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - - -import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { + ArgumentContext, + ArgumentsContext, + ArrayLiteralContext, + CollectionContext, + CommandContext, + CommandsContext, + CommentContext, + ElementListContext, + EmptyCommandContext, + FunctionCallContext, + LiteralContext, + MongoCommandsContext, + ObjectLiteralContext, + PropertyAssignmentContext, + PropertyNameAndValueListContext, + PropertyNameContext, + PropertyValueContext, +} from "./mongoParser"; /** * This interface defines a complete listener for a parse tree produced by @@ -143,12 +156,16 @@ export interface mongoListener extends ParseTreeListener { * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; + enterPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => void; /** * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. * @param ctx the parse tree */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; + exitPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => void; /** * Enter a parse tree produced by `mongoParser.propertyAssignment`. @@ -205,4 +222,3 @@ export interface mongoListener extends ParseTreeListener { */ exitComment?: (ctx: CommentContext) => void; } - diff --git a/Source/mongo/grammar/mongoParser.ts b/Source/mongo/grammar/mongoParser.ts index c1d38f4d0..f08e3ff51 100644 --- a/Source/mongo/grammar/mongoParser.ts +++ b/Source/mongo/grammar/mongoParser.ts @@ -9,1458 +9,1650 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { TokenStream } from 'antlr4ts/TokenStream'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { mongoListener } from './mongoListener'; -import { mongoVisitor } from './mongoVisitor'; - - - +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; +import { NotNull, Override } from "antlr4ts/Decorators"; +import * as Utils from "antlr4ts/misc/Utils"; +import { NoViableAltException } from "antlr4ts/NoViableAltException"; +import { Parser } from "antlr4ts/Parser"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { RuleVersion } from "antlr4ts/RuleVersion"; +import { Token } from "antlr4ts/Token"; +import { TokenStream } from "antlr4ts/TokenStream"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; +import { mongoListener } from "./mongoListener"; +import { mongoVisitor } from "./mongoVisitor"; export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - "mongoCommands", "commands", "command", "emptyCommand", "collection", - "functionCall", "arguments", "argument", "objectLiteral", "arrayLiteral", - "elementList", "propertyNameAndValueList", "propertyAssignment", "propertyValue", - "literal", "propertyName", "comment" - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined, - undefined, undefined, undefined, "'null'", undefined, undefined, undefined, - undefined, "';'", "'.'", "'db'" - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, undefined, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment", - "StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", - "LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL", - "SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE" - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoParser._LITERAL_NAMES, mongoParser._SYMBOLIC_NAMES, []); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { return "mongo.g4"; } - - @Override - public get ruleNames(): string[] { return mongoParser.ruleNames; } - - @Override - public get serializedATN(): string { return mongoParser._serializedATN; } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.SingleLineComment) | (1 << mongoParser.MultiLineComment) | (1 << mongoParser.SEMICOLON) | (1 << mongoParser.DB))) !== 0)) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral))) !== 0)) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.T__3) | (1 << mongoParser.T__5) | (1 << mongoParser.RegexLiteral) | (1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral) | (1 << mongoParser.NumericLiteral) | (1 << mongoParser.IDENTIFIER))) !== 0)) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << mongoParser.StringLiteral) | (1 << mongoParser.NullLiteral) | (1 << mongoParser.BooleanLiteral))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + - "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + - "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + - "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + - "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + - "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + - "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + - "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + - "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + - "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + - "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + - "\x1C\x02\x1E\x02 \x02\"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17" + - "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + - "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + - "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + - "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + - "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + - "\x02\x02\"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03" + - "\x03\x02\x02\x02\'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*\'" + - "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + - ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + - "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + - "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + - "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + - "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + - "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + - "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + - "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + - "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + - "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + - "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + - "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + - "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + - "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + - "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + - "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + - "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + - "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + - "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + - "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + - "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + - "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + - "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + - "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + - "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + - "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + - "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + - "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + - "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + - "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + - "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + - "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } - + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly T__7 = 8; + public static readonly RegexLiteral = 9; + public static readonly SingleLineComment = 10; + public static readonly MultiLineComment = 11; + public static readonly StringLiteral = 12; + public static readonly NullLiteral = 13; + public static readonly BooleanLiteral = 14; + public static readonly NumericLiteral = 15; + public static readonly DecimalLiteral = 16; + public static readonly LineTerminator = 17; + public static readonly SEMICOLON = 18; + public static readonly DOT = 19; + public static readonly DB = 20; + public static readonly IDENTIFIER = 21; + public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; + public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; + public static readonly WHITESPACE = 24; + public static readonly RULE_mongoCommands = 0; + public static readonly RULE_commands = 1; + public static readonly RULE_command = 2; + public static readonly RULE_emptyCommand = 3; + public static readonly RULE_collection = 4; + public static readonly RULE_functionCall = 5; + public static readonly RULE_arguments = 6; + public static readonly RULE_argument = 7; + public static readonly RULE_objectLiteral = 8; + public static readonly RULE_arrayLiteral = 9; + public static readonly RULE_elementList = 10; + public static readonly RULE_propertyNameAndValueList = 11; + public static readonly RULE_propertyAssignment = 12; + public static readonly RULE_propertyValue = 13; + public static readonly RULE_literal = 14; + public static readonly RULE_propertyName = 15; + public static readonly RULE_comment = 16; + public static readonly ruleNames: string[] = [ + "mongoCommands", + "commands", + "command", + "emptyCommand", + "collection", + "functionCall", + "arguments", + "argument", + "objectLiteral", + "arrayLiteral", + "elementList", + "propertyNameAndValueList", + "propertyAssignment", + "propertyValue", + "literal", + "propertyName", + "comment", + ]; + + private static readonly _LITERAL_NAMES: (string | undefined)[] = [ + undefined, + "'('", + "','", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "':'", + undefined, + undefined, + undefined, + undefined, + "'null'", + undefined, + undefined, + undefined, + undefined, + "';'", + "'.'", + "'db'", + ]; + private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + "RegexLiteral", + "SingleLineComment", + "MultiLineComment", + "StringLiteral", + "NullLiteral", + "BooleanLiteral", + "NumericLiteral", + "DecimalLiteral", + "LineTerminator", + "SEMICOLON", + "DOT", + "DB", + "IDENTIFIER", + "DOUBLE_QUOTED_STRING_LITERAL", + "SINGLE_QUOTED_STRING_LITERAL", + "WHITESPACE", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( + mongoParser._LITERAL_NAMES, + mongoParser._SYMBOLIC_NAMES, + [] + ); + + @Override + @NotNull + public get vocabulary(): Vocabulary { + return mongoParser.VOCABULARY; + } + + @Override + public get grammarFileName(): string { + return "mongo.g4"; + } + + @Override + public get ruleNames(): string[] { + return mongoParser.ruleNames; + } + + @Override + public get serializedATN(): string { + return mongoParser._serializedATN; + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(mongoParser._ATN, this); + } + @RuleVersion(0) + public mongoCommands(): MongoCommandsContext { + const _localctx: MongoCommandsContext = new MongoCommandsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 34; + this.commands(); + this.state = 35; + this.match(mongoParser.EOF); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public commands(): CommandsContext { + const _localctx: CommandsContext = new CommandsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 2, mongoParser.RULE_commands); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 42; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.SingleLineComment) | + (1 << mongoParser.MultiLineComment) | + (1 << mongoParser.SEMICOLON) | + (1 << mongoParser.DB))) !== + 0 + ) { + { + this.state = 40; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.DB: + { + this.state = 37; + this.command(); + } + break; + case mongoParser.SEMICOLON: + { + this.state = 38; + this.emptyCommand(); + } + break; + case mongoParser.SingleLineComment: + case mongoParser.MultiLineComment: + { + this.state = 39; + this.comment(); + } + break; + default: + throw new NoViableAltException(this); + } + } + this.state = 44; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public command(): CommandContext { + const _localctx: CommandContext = new CommandContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 4, mongoParser.RULE_command); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 45; + this.match(mongoParser.DB); + this.state = 48; + this._errHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this._input, 2, this._ctx) + ) { + case 1: + { + this.state = 46; + this.match(mongoParser.DOT); + this.state = 47; + this.collection(); + } + break; + } + this.state = 52; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 50; + this.match(mongoParser.DOT); + this.state = 51; + this.functionCall(); + } + } + this.state = 54; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la === mongoParser.DOT); + this.state = 57; + this._errHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this._input, 4, this._ctx) + ) { + case 1: + { + this.state = 56; + this.match(mongoParser.SEMICOLON); + } + break; + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public emptyCommand(): EmptyCommandContext { + const _localctx: EmptyCommandContext = new EmptyCommandContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 59; + this.match(mongoParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public collection(): CollectionContext { + const _localctx: CollectionContext = new CollectionContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 8, mongoParser.RULE_collection); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 61; + this.match(mongoParser.IDENTIFIER); + this.state = 66; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 5, + this._ctx + ); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 62; + this.match(mongoParser.DOT); + this.state = 63; + this.match(mongoParser.IDENTIFIER); + } + } + } + this.state = 68; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 5, + this._ctx + ); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public functionCall(): FunctionCallContext { + const _localctx: FunctionCallContext = new FunctionCallContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 69; + _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); + this.state = 70; + this.arguments(); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arguments(): ArgumentsContext { + const _localctx: ArgumentsContext = new ArgumentsContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 12, mongoParser.RULE_arguments); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 72; + _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); + this.state = 81; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.T__3) | + (1 << mongoParser.T__5) | + (1 << mongoParser.RegexLiteral) | + (1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral) | + (1 << mongoParser.NumericLiteral))) !== + 0 + ) { + { + this.state = 73; + this.argument(); + this.state = 78; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 74; + this.match(mongoParser.T__1); + this.state = 75; + this.argument(); + } + } + this.state = 80; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + this.state = 83; + _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public argument(): ArgumentContext { + const _localctx: ArgumentContext = new ArgumentContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 14, mongoParser.RULE_argument); + try { + this.state = 88; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 85; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 86; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 87; + this.arrayLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public objectLiteral(): ObjectLiteralContext { + const _localctx: ObjectLiteralContext = new ObjectLiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 90; + this.match(mongoParser.T__3); + this.state = 92; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + _la === mongoParser.StringLiteral || + _la === mongoParser.IDENTIFIER + ) { + { + this.state = 91; + this.propertyNameAndValueList(); + } + } + + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === mongoParser.T__1) { + { + this.state = 94; + this.match(mongoParser.T__1); + } + } + + this.state = 97; + this.match(mongoParser.T__4); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public arrayLiteral(): ArrayLiteralContext { + const _localctx: ArrayLiteralContext = new ArrayLiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 99; + this.match(mongoParser.T__5); + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.T__3) | + (1 << mongoParser.T__5) | + (1 << mongoParser.RegexLiteral) | + (1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral) | + (1 << mongoParser.NumericLiteral) | + (1 << mongoParser.IDENTIFIER))) !== + 0 + ) { + { + this.state = 100; + this.elementList(); + } + } + + this.state = 103; + this.match(mongoParser.T__6); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public elementList(): ElementListContext { + const _localctx: ElementListContext = new ElementListContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 20, mongoParser.RULE_elementList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 105; + this.propertyValue(); + this.state = 110; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === mongoParser.T__1) { + { + { + this.state = 106; + this.match(mongoParser.T__1); + this.state = 107; + this.propertyValue(); + } + } + this.state = 112; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyNameAndValueList(): PropertyNameAndValueListContext { + const _localctx: PropertyNameAndValueListContext = + new PropertyNameAndValueListContext(this._ctx, this.state); + this.enterRule( + _localctx, + 22, + mongoParser.RULE_propertyNameAndValueList + ); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 113; + this.propertyAssignment(); + this.state = 118; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 13, + this._ctx + ); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 114; + this.match(mongoParser.T__1); + this.state = 115; + this.propertyAssignment(); + } + } + } + this.state = 120; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict( + this._input, + 13, + this._ctx + ); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyAssignment(): PropertyAssignmentContext { + const _localctx: PropertyAssignmentContext = + new PropertyAssignmentContext(this._ctx, this.state); + this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 121; + this.propertyName(); + this.state = 122; + this.match(mongoParser.T__7); + this.state = 123; + this.propertyValue(); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyValue(): PropertyValueContext { + const _localctx: PropertyValueContext = new PropertyValueContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); + try { + this.state = 129; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.RegexLiteral: + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 125; + this.literal(); + } + break; + case mongoParser.T__3: + this.enterOuterAlt(_localctx, 2); + { + this.state = 126; + this.objectLiteral(); + } + break; + case mongoParser.T__5: + this.enterOuterAlt(_localctx, 3); + { + this.state = 127; + this.arrayLiteral(); + } + break; + case mongoParser.IDENTIFIER: + this.enterOuterAlt(_localctx, 4); + { + this.state = 128; + this.functionCall(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public literal(): LiteralContext { + const _localctx: LiteralContext = new LiteralContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 28, mongoParser.RULE_literal); + let _la: number; + try { + this.state = 134; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case mongoParser.StringLiteral: + case mongoParser.NullLiteral: + case mongoParser.BooleanLiteral: + this.enterOuterAlt(_localctx, 1); + { + this.state = 131; + _la = this._input.LA(1); + if ( + !( + (_la & ~0x1f) === 0 && + ((1 << _la) & + ((1 << mongoParser.StringLiteral) | + (1 << mongoParser.NullLiteral) | + (1 << mongoParser.BooleanLiteral))) !== + 0 + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + break; + case mongoParser.RegexLiteral: + this.enterOuterAlt(_localctx, 2); + { + this.state = 132; + this.match(mongoParser.RegexLiteral); + } + break; + case mongoParser.NumericLiteral: + this.enterOuterAlt(_localctx, 3); + { + this.state = 133; + this.match(mongoParser.NumericLiteral); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public propertyName(): PropertyNameContext { + const _localctx: PropertyNameContext = new PropertyNameContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 136; + _la = this._input.LA(1); + if ( + !( + _la === mongoParser.StringLiteral || + _la === mongoParser.IDENTIFIER + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + @RuleVersion(0) + public comment(): CommentContext { + const _localctx: CommentContext = new CommentContext( + this._ctx, + this.state + ); + this.enterRule(_localctx, 32, mongoParser.RULE_comment); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 138; + _la = this._input.LA(1); + if ( + !( + _la === mongoParser.SingleLineComment || + _la === mongoParser.MultiLineComment + ) + ) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return _localctx; + } + + public static readonly _serializedATN: string = + "\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03" + + "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E" + + "\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06" + + "\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07" + + "\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b" + + "\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n" + + "\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f" + + "\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E" + + "\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F" + + "\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03" + + "\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b" + + "\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02" + + '\x1C\x02\x1E\x02 \x02"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17' + + "\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03" + + "\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02" + + "\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e" + + "\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02" + + "\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02" + + '\x02\x02"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03' + + "\x03\x02\x02\x02'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*'" + + "\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02" + + ",*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02" + + "\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02" + + "\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07" + + "\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02" + + "\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02" + + "\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17" + + "\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02" + + "\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03" + + "\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07" + + "\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02" + + "\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02" + + "\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02" + + "\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05" + + "\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02" + + "\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03" + + "\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03" + + "\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13" + + "\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03" + + "\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp" + + "\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02" + + "or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02" + + "\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E" + + "\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02" + + "\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02" + + "\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80" + + "\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F" + + "\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82" + + "\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89" + + "\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86" + + "\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B" + + "\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02" + + "\x02\x02\x12*,28;DPSZ^agpx\x83\x88"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!mongoParser.__ATN) { + mongoParser.__ATN = new ATNDeserializer().deserialize( + Utils.toCharArray(mongoParser._serializedATN) + ); + } + + return mongoParser.__ATN; + } } export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { return this.getToken(mongoParser.EOF, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_mongoCommands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } + public commands(): CommandsContext { + return this.getRuleContext(0, CommandsContext); + } + public EOF(): TerminalNode { + return this.getToken(mongoParser.EOF, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_mongoCommands; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterMongoCommands) listener.enterMongoCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitMongoCommands) listener.exitMongoCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); + else return visitor.visitChildren(this); + } } - export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_commands; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } + public command(): CommandContext[]; + public command(i: number): CommandContext; + public command(i?: number): CommandContext | CommandContext[] { + if (i === undefined) { + return this.getRuleContexts(CommandContext); + } else { + return this.getRuleContext(i, CommandContext); + } + } + public emptyCommand(): EmptyCommandContext[]; + public emptyCommand(i: number): EmptyCommandContext; + public emptyCommand( + i?: number + ): EmptyCommandContext | EmptyCommandContext[] { + if (i === undefined) { + return this.getRuleContexts(EmptyCommandContext); + } else { + return this.getRuleContext(i, EmptyCommandContext); + } + } + public comment(): CommentContext[]; + public comment(i: number): CommentContext; + public comment(i?: number): CommentContext | CommentContext[] { + if (i === undefined) { + return this.getRuleContexts(CommentContext); + } else { + return this.getRuleContext(i, CommentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_commands; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommands) listener.enterCommands(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommands) listener.exitCommands(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommands) return visitor.visitCommands(this); + else return visitor.visitChildren(this); + } } - export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { return this.getToken(mongoParser.DB, 0); } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_command; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } + public DB(): TerminalNode { + return this.getToken(mongoParser.DB, 0); + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + public collection(): CollectionContext | undefined { + return this.tryGetRuleContext(0, CollectionContext); + } + public functionCall(): FunctionCallContext[]; + public functionCall(i: number): FunctionCallContext; + public functionCall( + i?: number + ): FunctionCallContext | FunctionCallContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionCallContext); + } else { + return this.getRuleContext(i, FunctionCallContext); + } + } + public SEMICOLON(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.SEMICOLON, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_command; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCommand) listener.enterCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCommand) listener.exitCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCommand) return visitor.visitCommand(this); + else return visitor.visitChildren(this); + } } - export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { return this.getToken(mongoParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_emptyCommand; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } + public SEMICOLON(): TerminalNode { + return this.getToken(mongoParser.SEMICOLON, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_emptyCommand; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); + else return visitor.visitChildren(this); + } } - export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_collection; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.IDENTIFIER); + } else { + return this.getToken(mongoParser.IDENTIFIER, i); + } + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(mongoParser.DOT); + } else { + return this.getToken(mongoParser.DOT, i); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_collection; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterCollection) listener.enterCollection(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitCollection) listener.exitCollection(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitCollection) return visitor.visitCollection(this); + else return visitor.visitChildren(this); + } } - export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { return this.getToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_functionCall; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } + public _FUNCTION_NAME: Token; + public arguments(): ArgumentsContext { + return this.getRuleContext(0, ArgumentsContext); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(mongoParser.IDENTIFIER, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_functionCall; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterFunctionCall) listener.enterFunctionCall(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitFunctionCall) listener.exitFunctionCall(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); + else return visitor.visitChildren(this); + } } - export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arguments; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } + public _OPEN_PARENTHESIS: Token; + public _CLOSED_PARENTHESIS: Token; + public argument(): ArgumentContext[]; + public argument(i: number): ArgumentContext; + public argument(i?: number): ArgumentContext | ArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(ArgumentContext); + } else { + return this.getRuleContext(i, ArgumentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_arguments; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArguments) listener.enterArguments(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArguments) listener.exitArguments(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArguments) return visitor.visitArguments(this); + else return visitor.visitChildren(this); + } } - export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_argument; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_argument; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArgument) listener.enterArgument(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArgument) listener.exitArgument(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArgument) return visitor.visitArgument(this); + else return visitor.visitChildren(this); + } } - export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_objectLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } + public propertyNameAndValueList(): + | PropertyNameAndValueListContext + | undefined { + return this.tryGetRuleContext(0, PropertyNameAndValueListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_objectLiteral; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); + else return visitor.visitChildren(this); + } } - export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_arrayLiteral; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } + public elementList(): ElementListContext | undefined { + return this.tryGetRuleContext(0, ElementListContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_arrayLiteral; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); + else return visitor.visitChildren(this); + } } - export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_elementList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } + public propertyValue(): PropertyValueContext[]; + public propertyValue(i: number): PropertyValueContext; + public propertyValue( + i?: number + ): PropertyValueContext | PropertyValueContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyValueContext); + } else { + return this.getRuleContext(i, PropertyValueContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_elementList; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterElementList) listener.enterElementList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitElementList) listener.exitElementList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitElementList) return visitor.visitElementList(this); + else return visitor.visitChildren(this); + } } - export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyNameAndValueList; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } + public propertyAssignment(): PropertyAssignmentContext[]; + public propertyAssignment(i: number): PropertyAssignmentContext; + public propertyAssignment( + i?: number + ): PropertyAssignmentContext | PropertyAssignmentContext[] { + if (i === undefined) { + return this.getRuleContexts(PropertyAssignmentContext); + } else { + return this.getRuleContext(i, PropertyAssignmentContext); + } + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyNameAndValueList; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyNameAndValueList) + listener.enterPropertyNameAndValueList(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyNameAndValueList) + listener.exitPropertyNameAndValueList(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyNameAndValueList) + return visitor.visitPropertyNameAndValueList(this); + else return visitor.visitChildren(this); + } } - export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyAssignment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } + public propertyName(): PropertyNameContext { + return this.getRuleContext(0, PropertyNameContext); + } + public propertyValue(): PropertyValueContext { + return this.getRuleContext(0, PropertyValueContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyAssignment; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyAssignment) + listener.enterPropertyAssignment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyAssignment) + listener.exitPropertyAssignment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyAssignment) + return visitor.visitPropertyAssignment(this); + else return visitor.visitChildren(this); + } } - export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyValue; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } + public literal(): LiteralContext | undefined { + return this.tryGetRuleContext(0, LiteralContext); + } + public objectLiteral(): ObjectLiteralContext | undefined { + return this.tryGetRuleContext(0, ObjectLiteralContext); + } + public arrayLiteral(): ArrayLiteralContext | undefined { + return this.tryGetRuleContext(0, ArrayLiteralContext); + } + public functionCall(): FunctionCallContext | undefined { + return this.tryGetRuleContext(0, FunctionCallContext); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyValue; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyValue) listener.enterPropertyValue(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyValue) listener.exitPropertyValue(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); + else return visitor.visitChildren(this); + } } - export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NullLiteral, 0); } - public BooleanLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.BooleanLiteral, 0); } - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public RegexLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.RegexLiteral, 0); } - public NumericLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.NumericLiteral, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_literal; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } + public NullLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.NullLiteral, 0); + } + public BooleanLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.BooleanLiteral, 0); + } + public StringLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.StringLiteral, 0); + } + public RegexLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.RegexLiteral, 0); + } + public NumericLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.NumericLiteral, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_literal; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterLiteral) listener.enterLiteral(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitLiteral) listener.exitLiteral(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitLiteral) return visitor.visitLiteral(this); + else return visitor.visitChildren(this); + } } - export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { return this.tryGetToken(mongoParser.StringLiteral, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(mongoParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_propertyName; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } + public StringLiteral(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.StringLiteral, 0); + } + public IDENTIFIER(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.IDENTIFIER, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_propertyName; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterPropertyName) listener.enterPropertyName(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitPropertyName) listener.exitPropertyName(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitPropertyName) return visitor.visitPropertyName(this); + else return visitor.visitChildren(this); + } } - export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.SingleLineComment, 0); } - public MultiLineComment(): TerminalNode | undefined { return this.tryGetToken(mongoParser.MultiLineComment, 0); } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - - } - @Override public get ruleIndex(): number { return mongoParser.RULE_comment; } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } + public SingleLineComment(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.SingleLineComment, 0); + } + public MultiLineComment(): TerminalNode | undefined { + return this.tryGetToken(mongoParser.MultiLineComment, 0); + } + constructor(parent: ParserRuleContext, invokingState: number); + constructor(parent: ParserRuleContext, invokingState: number) { + super(parent, invokingState); + } + @Override public get ruleIndex(): number { + return mongoParser.RULE_comment; + } + @Override + public enterRule(listener: mongoListener): void { + if (listener.enterComment) listener.enterComment(this); + } + @Override + public exitRule(listener: mongoListener): void { + if (listener.exitComment) listener.exitComment(this); + } + @Override + public accept(visitor: mongoVisitor): Result { + if (visitor.visitComment) return visitor.visitComment(this); + else return visitor.visitChildren(this); + } } - - diff --git a/Source/mongo/grammar/mongoVisitor.ts b/Source/mongo/grammar/mongoVisitor.ts index eb001a6e9..105184d2d 100644 --- a/Source/mongo/grammar/mongoVisitor.ts +++ b/Source/mongo/grammar/mongoVisitor.ts @@ -1,17 +1,30 @@ // Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - - -import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser'; - - +import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; +import { + ArgumentContext, + ArgumentsContext, + ArrayLiteralContext, + CollectionContext, + CommandContext, + CommandsContext, + CommentContext, + ElementListContext, + EmptyCommandContext, + FunctionCallContext, + LiteralContext, + MongoCommandsContext, + ObjectLiteralContext, + PropertyAssignmentContext, + PropertyNameAndValueListContext, + PropertyNameContext, + PropertyValueContext, +} from "./mongoParser"; /** * This interface defines a complete generic visitor for a parse tree produced @@ -103,7 +116,9 @@ export interface mongoVisitor extends ParseTreeVisitor { * @param ctx the parse tree * @return the visitor result */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; + visitPropertyNameAndValueList?: ( + ctx: PropertyNameAndValueListContext + ) => Result; /** * Visit a parse tree produced by `mongoParser.propertyAssignment`. @@ -140,4 +155,3 @@ export interface mongoVisitor extends ParseTreeVisitor { */ visitComment?: (ctx: CommentContext) => Result; } - diff --git a/Source/mongo/grammar/visitors.ts b/Source/mongo/grammar/visitors.ts index e1ba1b63d..20e69315d 100644 --- a/Source/mongo/grammar/visitors.ts +++ b/Source/mongo/grammar/visitors.ts @@ -3,81 +3,88 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser'; -import { mongoVisitor } from './mongoVisitor'; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { + ArgumentContext, + ArgumentsContext, + CollectionContext, + CommandContext, + CommandsContext, + FunctionCallContext, + MongoCommandsContext, +} from "./mongoParser"; +import { mongoVisitor } from "./mongoVisitor"; export class MongoVisitor implements mongoVisitor { - - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return null; - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } + visitMongoCommands(ctx: MongoCommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommands(ctx: CommandsContext): T { + return this.visitChildren(ctx); + } + + visitCommand(ctx: CommandContext): T { + return this.visitChildren(ctx); + } + + visitCollection(ctx: CollectionContext): T { + return this.visitChildren(ctx); + } + + visitFunctionCall(ctx: FunctionCallContext): T { + return this.visitChildren(ctx); + } + + visitArgument(ctx: ArgumentContext): T { + return this.visitChildren(ctx); + } + + visitArguments(ctx: ArgumentsContext): T { + return this.visitChildren(ctx); + } + + visit(tree: ParseTree): T { + return tree.accept(this); + } + + visitChildren(ctx: ParserRuleContext): T { + let result = this.defaultResult(ctx); + const n = ctx.childCount; + for (let i = 0; i < n; i++) { + if (!this.shouldVisitNextChild(ctx, result)) { + break; + } + + const childNode = ctx.getChild(i); + const childResult = childNode.accept(this); + result = this.aggregateResult(result, childResult); + } + return result; + } + + visitTerminal(node: TerminalNode): T { + return this.defaultResult(node); + } + + visitErrorNode(node: ErrorNode): T { + return this.defaultResult(node); + } + + protected defaultResult(_node: ParseTree): T { + // grandfathered-in. Unclear why this is null instead of type T + return (null); + } + + protected aggregateResult(aggregate: T, nextResult: T): T { + return !nextResult ? aggregate : nextResult; + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + shouldVisitNextChild(_node, _currentResult: T): boolean { + return true; + } } diff --git a/Source/mongo/languageClient.ts b/Source/mongo/languageClient.ts index e4bd4aefd..6f445423e 100644 --- a/Source/mongo/languageClient.ts +++ b/Source/mongo/languageClient.ts @@ -2,57 +2,81 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -import * as nls from 'vscode-nls'; -import { ext } from '../extensionVariables'; -import { IConnectionParams } from './services/IConnectionParams'; +import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils"; +import * as path from "path"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from "vscode-languageclient"; +import * as nls from "vscode-nls"; +import { ext } from "../extensionVariables"; +import { IConnectionParams } from "./services/IConnectionParams"; const localize = nls.loadMessageBundle(); export class MongoDBLanguageClient { + public client: LanguageClient; - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverModule = ext.ignoreBundle ? - ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) : - ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js')); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'mongo', scheme: 'file' }, - { language: 'mongo', scheme: 'untitled' } - ] - }; - - // Create the language client and start the client. - this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions); - const disposable = this.client.start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push(disposable); - } - - public async connect(connectionString: string, databaseName: string): Promise { - await this.client.sendRequest('connect', { connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } + constructor() { + // The server is implemented in node + const serverModule = ext.ignoreBundle + ? ext.context.asAbsolutePath( + path.join("out", "src", "mongo", "languageServer.js") + ) + : ext.context.asAbsolutePath( + path.join("dist", "mongo-languageServer.bundle.js") + ); + // The debug options for the server + const debugOptions = { execArgv: ["--nolazy", "--inspect=6005"] }; + + // If the extension is launch in debug mode the debug server options are use + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + options: debugOptions, + }, + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for mongo javascript documents + documentSelector: [ + { language: "mongo", scheme: "file" }, + { language: "mongo", scheme: "untitled" }, + ], + }; + + // Create the language client and start the client. + this.client = new LanguageClient( + "mongo", + localize("mongo.server.name", "Mongo Language Server"), + serverOptions, + clientOptions + ); + const disposable = this.client.start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + ext.context.subscriptions.push(disposable); + } + + public async connect( + connectionString: string, + databaseName: string + ): Promise { + await this.client.sendRequest("connect", { + connectionString: connectionString, + databaseName: databaseName, + extensionUserAgent: appendExtensionUserAgent(), + }); + } + + public async disconnect(): Promise { + await this.client.sendRequest("disconnect"); + } } diff --git a/Source/mongo/languageServer.ts b/Source/mongo/languageServer.ts index d5d6ec484..8c76686f6 100644 --- a/Source/mongo/languageServer.ts +++ b/Source/mongo/languageServer.ts @@ -2,8 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createConnection, IConnection } from 'vscode-languageserver'; -import { LanguageService } from './services/languageService'; +import { createConnection, IConnection } from "vscode-languageserver"; +import { LanguageService } from "./services/languageService"; // // diff --git a/Source/mongo/mongoConnectionStrings.ts b/Source/mongo/mongoConnectionStrings.ts index 5f73db484..89d04ed30 100644 --- a/Source/mongo/mongoConnectionStrings.ts +++ b/Source/mongo/mongoConnectionStrings.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; +import { + appendExtensionUserAgent, + IParsedError, + parseError, +} from "@microsoft/vscode-azext-utils"; import { MongoClient } from "mongodb"; import { testDb } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; @@ -21,84 +25,118 @@ import { connectToMongoClient } from "./connectToMongoClient"; // mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] // [database] -const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)'; -const parseDatabaseName = '\/?([^/?]+)?'; +const parsePrefix = "([a-zA-Z]+://[^/]*)"; +const parseDatabaseName = "/?([^/?]+)?"; const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch'); - return databaseName; - } catch (error) { - // Shouldn't happen, but ignore if does - } +export function getDatabaseNameFromConnectionString( + connectionString: string +): string | undefined { + try { + const [, , databaseName] = nonNullValue( + connectionString.match(mongoConnectionStringRegExp), + "databaseNameMatch" + ); + return databaseName; + } catch (error) { + // Shouldn't happen, but ignore if does + } - return undefined; + return undefined; } -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`); - } catch (error) { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } +export function addDatabaseToAccountConnectionString( + connectionString: string, + databaseName: string +): string { + try { + return connectionString.replace( + mongoConnectionStringRegExp, + `$1\/${encodeURIComponent(databaseName)}` + ); + } catch (error) { + // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it + return connectionString; + } } -export async function parseMongoConnectionString(connectionString: string): Promise { +export async function parseMongoConnectionString( + connectionString: string +): Promise { + let mongoClient: MongoClient; + try { + mongoClient = await connectToMongoClient( + connectionString, + appendExtensionUserAgent() + ); + } catch (error) { + const parsedError: IParsedError = parseError(error); + if (parsedError.message.match(/unescaped/i)) { + // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 + connectionString = encodeMongoConnectionString(connectionString); + mongoClient = await connectToMongoClient( + connectionString, + appendExtensionUserAgent() + ); + } else { + throw error; + } + } - let mongoClient: MongoClient; - try { - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const serverConfig: any = mongoClient.db(testDb).serverConfig; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverConfig: any = mongoClient.db(testDb).serverConfig; + // get the first connection string from the servers list + // this may not be best solution, but the connection (below) gives + // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) + // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const host: string = + serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const port: string = + serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - // get the first connection string from the servers list - // this may not be best solution, but the connection (below) gives - // host name of single server, mongos instance or the primany from replicaSet which is different than what is in the connection string (espcially for Replica sets) - // "s" is not part of the static definition but can't find any official documentation on it. Yet it is definitely there at runtime. Grandfathering in. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const host: string = serverConfig?.s?.options?.servers[0]?.host || serverConfig.host; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const port: string = serverConfig?.s?.options?.servers[0]?.port || serverConfig.port; - - return new ParsedMongoConnectionString(connectionString, host, port, getDatabaseNameFromConnectionString(connectionString)); + return new ParsedMongoConnectionString( + connectionString, + host, + port, + getDatabaseNameFromConnectionString(connectionString) + ); } export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; + public readonly hostName: string; + public readonly port: string; - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } + constructor( + connectionString: string, + hostName: string, + port: string, + databaseName: string | undefined + ) { + super(connectionString, databaseName); + this.hostName = hostName; + this.port = port; + } } /** * Encodes the username and password in the given Mongo DB connection string. */ export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } + const matches: RegExpMatchArray | null = connectionString.match( + /^(.*):\/\/(.*):(.*)@(.*)/ + ); + if (matches) { + const prefix: string = matches[1]; + const username: string = matches[2]; + const password: string = matches[3]; + const hostAndQuery: string = matches[4]; + connectionString = `${prefix}://${encodeURIComponent( + username + )}:${encodeURIComponent(password)}@${hostAndQuery}`; + } - return connectionString; + return connectionString; } diff --git a/Source/mongo/registerMongoCommands.ts b/Source/mongo/registerMongoCommands.ts index 2dc36477a..713ff9104 100644 --- a/Source/mongo/registerMongoCommands.ts +++ b/Source/mongo/registerMongoCommands.ts @@ -3,15 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; -import { Experience, MongoExperience } from '../AzureDBExperiences'; +import { + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, + IErrorHandlerContext, + ITreeItemPickerContext, + registerCommandWithTreeNodeUnwrapping, + registerErrorHandler, + registerEvent, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { Experience, MongoExperience } from "../AzureDBExperiences"; import { cosmosMongoFilter } from "../constants"; import { ext } from "../extensionVariables"; -import * as vscodeUtil from '../utils/vscodeUtils'; -import { MongoConnectError } from './connectToMongoClient'; +import * as vscodeUtil from "../utils/vscodeUtils"; +import { MongoConnectError } from "./connectToMongoClient"; import { MongoDBLanguageClient } from "./languageClient"; -import { executeAllCommandsFromActiveEditor, executeCommandFromActiveEditor, getAllErrorsFromTextDocument } from "./MongoScrapbook"; +import { + executeAllCommandsFromActiveEditor, + executeCommandFromActiveEditor, + getAllErrorsFromTextDocument, +} from "./MongoScrapbook"; import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider"; import { setConnectedNode } from "./setConnectedNode"; import { MongoAccountTreeItem } from "./tree/MongoAccountTreeItem"; @@ -19,205 +32,328 @@ import { MongoCollectionTreeItem } from "./tree/MongoCollectionTreeItem"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; import { MongoDocumentTreeItem } from "./tree/MongoDocumentTreeItem"; -const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB'; +const connectedMongoKey: string = "ms-azuretools.vscode-cosmosdb.connectedDB"; let diagnosticsCollection: vscode.DiagnosticCollection; -const mongoLanguageId: string = 'mongo'; +const mongoLanguageId: string = "mongo"; export function registerMongoCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.mongoCodeLensProvider = new MongoCodeLensProvider(); - ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider)); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); - - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDatabase', createMongoDatabase); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoCollection', createMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.createMongoDocument', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - const documentNode = await node.createChild(context); - await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.connectMongoDB', async (context: IActionContext, node?: MongoDatabaseTreeItem) => { - if (!node) { - // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 - const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience }; - node = await pickMongo(experienceContext, MongoDatabaseTreeItem.contextValue); - } - - const oldNodeId: string | undefined = ext.connectedMongoDB && ext.connectedMongoDB.fullId; - await ext.mongoLanguageClient.connect(node.connectionString, node.databaseName); - void ext.context.globalState.update(connectedMongoKey, node.fullId); - setConnectedNode(node); - await node.refresh(context); - - if (oldNodeId) { - // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldNode: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldNodeId, context); - if (oldNode) { - await oldNode.refresh(context); - } - } - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDB', deleteMongoDB); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoCollection', deleteMongoCollection); - registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteMongoDocument', async (context: IActionContext, node?: MongoDocumentTreeItem) => { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDocumentTreeItem.contextValue); - } - await node.deleteTreeItem(context); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.openCollection', async (context: IActionContext, node?: MongoCollectionTreeItem) => { - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await ext.fileSystem.showTextDocument(node); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.launchMongoShell', launchMongoShell); - registerCommandWithTreeNodeUnwrapping('cosmosDB.newMongoScrapbook', async () => await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo')); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeMongoCommand', async (context: IActionContext, position?: vscode.Position) => { - await loadPersistedMongoDBTask; - await executeCommandFromActiveEditor(context, position); - }); - registerCommandWithTreeNodeUnwrapping('cosmosDB.executeAllMongoCommands', async (context: IActionContext) => { - await loadPersistedMongoDBTask; - await executeAllCommandsFromActiveEditor(context); - }); + ext.mongoLanguageClient = new MongoDBLanguageClient(); + + ext.mongoCodeLensProvider = new MongoCodeLensProvider(); + ext.context.subscriptions.push( + vscode.languages.registerCodeLensProvider( + mongoLanguageId, + ext.mongoCodeLensProvider + ) + ); + + diagnosticsCollection = + vscode.languages.createDiagnosticCollection("cosmosDB.mongo"); + ext.context.subscriptions.push(diagnosticsCollection); + + setUpErrorReporting(); + + const loadPersistedMongoDBTask: Promise = loadPersistedMongoDB(); + + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoDatabase", + createMongoDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoCollection", + createMongoCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.createMongoDocument", + async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + const documentNode = await node.createChild(context); + await vscode.commands.executeCommand( + "cosmosDB.openDocument", + documentNode + ); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.connectMongoDB", + async (context: IActionContext, node?: MongoDatabaseTreeItem) => { + if (!node) { + // Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517 + const experienceContext: ITreeItemPickerContext & { + defaultExperience?: Experience; + } = { ...context, defaultExperience: MongoExperience }; + node = await pickMongo( + experienceContext, + MongoDatabaseTreeItem.contextValue + ); + } + + const oldNodeId: string | undefined = + ext.connectedMongoDB && ext.connectedMongoDB.fullId; + await ext.mongoLanguageClient.connect( + node.connectionString, + node.databaseName + ); + void ext.context.globalState.update(connectedMongoKey, node.fullId); + setConnectedNode(node); + await node.refresh(context); + + if (oldNodeId) { + // We have to use findTreeItem to get the instance of the old node that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldNode: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + oldNodeId, + context + ); + if (oldNode) { + await oldNode.refresh(context); + } + } + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoDB", + deleteMongoDB + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoCollection", + deleteMongoCollection + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.deleteMongoDocument", + async (context: IActionContext, node?: MongoDocumentTreeItem) => { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoDocumentTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.openCollection", + async (context: IActionContext, node?: MongoCollectionTreeItem) => { + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + await ext.fileSystem.showTextDocument(node); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.launchMongoShell", + launchMongoShell + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.newMongoScrapbook", + async () => await vscodeUtil.showNewFile("", "Scrapbook", ".mongo") + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.executeMongoCommand", + async (context: IActionContext, position?: vscode.Position) => { + await loadPersistedMongoDBTask; + await executeCommandFromActiveEditor(context, position); + } + ); + registerCommandWithTreeNodeUnwrapping( + "cosmosDB.executeAllMongoCommands", + async (context: IActionContext) => { + await loadPersistedMongoDBTask; + await executeAllCommandsFromActiveEditor(context); + } + ); } async function loadPersistedMongoDB(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; - - try { - const persistedNodeId: string | undefined = ext.context.globalState.get(connectedMongoKey); - if (persistedNodeId) { - const persistedNode = await ext.rgApi.appResourceTree.findTreeItem(persistedNodeId, context); - if (persistedNode) { - await ext.mongoLanguageClient.client.onReady(); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', persistedNode); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedMongoDB) { - ext.mongoCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling( + "cosmosDB.loadPersistedMongoDB", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = "true"; + + try { + const persistedNodeId: string | undefined = + ext.context.globalState.get(connectedMongoKey); + if (persistedNodeId) { + const persistedNode = + await ext.rgApi.appResourceTree.findTreeItem( + persistedNodeId, + context + ); + if (persistedNode) { + await ext.mongoLanguageClient.client.onReady(); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + persistedNode + ); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedMongoDB) { + ext.mongoCodeLensProvider.setConnectedDatabase(undefined); + } + } + } + ); } function launchMongoShell(): void { - const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell'); - terminal.sendText(`mongo`); - terminal.show(); + const terminal: vscode.Terminal = + vscode.window.createTerminal("Mongo Shell"); + terminal.sendText(`mongo`); + terminal.show(); } function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - "initialUpdateErrorsInActiveDocument", - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }); - - // Update errors when document opened/changed - registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === mongoLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); + // Update errors immediately in case a scrapbook is already open + void callWithTelemetryAndErrorHandling( + "initialUpdateErrorsInActiveDocument", + async (context: IActionContext) => { + updateErrorsInScrapbook( + context, + vscode.window.activeTextEditor?.document + ); + } + ); + + // Update errors when document opened/changed + registerEvent( + "vscode.workspace.onDidOpenTextDocument", + vscode.workspace.onDidOpenTextDocument, + updateErrorsInScrapbook + ); + registerEvent( + "vscode.workspace.onDidChangeTextDocument", + vscode.workspace.onDidChangeTextDocument, + async ( + context: IActionContext, + event: vscode.TextDocumentChangeEvent + ) => { + // Always suppress success telemetry - event happens on every keystroke + context.telemetry.suppressIfSuccessful = true; + + updateErrorsInScrapbook(context, event.document); + } + ); + registerEvent( + "vscode.workspace.onDidCloseTextDocument", + vscode.workspace.onDidCloseTextDocument, + async (context: IActionContext, document: vscode.TextDocument) => { + // Remove errors when closed + if (document?.languageId === mongoLanguageId) { + diagnosticsCollection.set(document.uri, []); + } else { + context.telemetry.suppressIfSuccessful = true; + } + } + ); + + registerErrorHandler((context: IErrorHandlerContext) => { + if (context.error instanceof MongoConnectError) { + context.errorHandling.suppressReportIssue = true; + } + }); } -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === mongoLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } +function updateErrorsInScrapbook( + context: IActionContext, + document: vscode.TextDocument | undefined +): void { + if (document?.languageId === mongoLanguageId) { + const errors = getAllErrorsFromTextDocument(document); + diagnosticsCollection.set(document.uri, errors); + } else { + context.telemetry.suppressIfSuccessful = true; + } } -export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise { - if (!node) { - node = await pickMongo(context); - } - const databaseNode = await node.createChild(context); - await databaseNode.createChild(context); +export async function createMongoDatabase( + context: IActionContext, + node?: MongoAccountTreeItem +): Promise { + if (!node) { + node = await pickMongo(context); + } + const databaseNode = await node.createChild(context); + await databaseNode.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', databaseNode); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + databaseNode + ); } -export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - const collectionNode = await node.createChild(context); - await vscode.commands.executeCommand('cosmosDB.connectMongoDB', collectionNode.parent); +export async function createMongoCollection( + context: IActionContext, + node?: MongoDatabaseTreeItem +): Promise { + if (!node) { + node = await pickMongo( + context, + MongoDatabaseTreeItem.contextValue + ); + } + const collectionNode = await node.createChild(context); + await vscode.commands.executeCommand( + "cosmosDB.connectMongoDB", + collectionNode.parent + ); } -export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoDatabaseTreeItem.contextValue); - } - await node.deleteTreeItem(context); - if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { - setConnectedNode(undefined); - void ext.context.globalState.update(connectedMongoKey, undefined); - // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 - void ext.mongoLanguageClient.disconnect(); - } +export async function deleteMongoDB( + context: IActionContext, + node?: MongoDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoDatabaseTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); + if (ext.connectedMongoDB && ext.connectedMongoDB.fullId === node.fullId) { + setConnectedNode(undefined); + void ext.context.globalState.update(connectedMongoKey, undefined); + // Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754 + void ext.mongoLanguageClient.disconnect(); + } } -export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await pickMongo(context, MongoCollectionTreeItem.contextValue); - } - await node.deleteTreeItem(context); +export async function deleteMongoCollection( + context: IActionContext, + node?: MongoCollectionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await pickMongo( + context, + MongoCollectionTreeItem.contextValue + ); + } + await node.deleteTreeItem(context); } -async function pickMongo(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise { - return await ext.rgApi.pickAppResource(context, { - filter: [ - cosmosMongoFilter - ], - expectedChildContextValue: expectedContextValue - }); +async function pickMongo( + context: IActionContext, + expectedContextValue?: string | RegExp | (string | RegExp)[] +): Promise { + return await ext.rgApi.pickAppResource(context, { + filter: [cosmosMongoFilter], + expectedChildContextValue: expectedContextValue, + }); } diff --git a/Source/mongo/services/IConnectionParams.ts b/Source/mongo/services/IConnectionParams.ts index eec39e4cf..55d2cc73a 100644 --- a/Source/mongo/services/IConnectionParams.ts +++ b/Source/mongo/services/IConnectionParams.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; + connectionString: string; + databaseName: string; + extensionUserAgent: string; } diff --git a/Source/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts index 3407c50dd..01aaff56f 100644 --- a/Source/mongo/services/MongoCodeLensProvider.ts +++ b/Source/mongo/services/MongoCodeLensProvider.ts @@ -3,73 +3,89 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import * as vscode from "vscode"; import { getAllCommandsFromTextDocument } from "../MongoScrapbook"; export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: vscode.EventEmitter = + new vscode.EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): vscode.Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses( + document: vscode.TextDocument, + _token: vscode.CancellationToken + ): vscode.ProviderResult { + return callWithTelemetryAndErrorHandling( + "mongo.provideCodeLenses", + (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: vscode.CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: vscode.CodeLens[] = []; - // Allow displaying and changing connected database - lenses.push({ - command: { - title: !isInitialized ? - 'Initializing...' : - isConnected ? - `Connected to ${database}` : - `Connect to a database`, - command: isInitialized && 'cosmosDB.connectMongoDB' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title: !isInitialized + ? "Initializing..." + : isConnected + ? `Connected to ${database}` + : `Connect to a database`, + command: isInitialized && "cosmosDB.connectMongoDB", + }, + range: new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(0, 0) + ), + }); - if (isConnected) { - // Run all - lenses.push({ - command: { - title: "Execute All", - command: 'cosmosDB.executeAllMongoCommands' - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)) - }); + if (isConnected) { + // Run all + lenses.push({ + command: { + title: "Execute All", + command: "cosmosDB.executeAllMongoCommands", + }, + range: new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(0, 0) + ), + }); - const commands = getAllCommandsFromTextDocument(document); - for (const cmd of commands) { - // run individual - lenses.push({ - command: { - title: "Execute", - command: 'cosmosDB.executeMongoCommand', - arguments: [cmd.range.start] - }, - range: cmd.range - }); - } - } + const commands = getAllCommandsFromTextDocument(document); + for (const cmd of commands) { + // run individual + lenses.push({ + command: { + title: "Execute", + command: "cosmosDB.executeMongoCommand", + arguments: [cmd.range.start], + }, + range: cmd.range, + }); + } + } - return lenses; - }); - } + return lenses; + } + ); + } } diff --git a/Source/mongo/services/completionItemProvider.ts b/Source/mongo/services/completionItemProvider.ts index cba51890c..4abb71432 100644 --- a/Source/mongo/services/completionItemProvider.ts +++ b/Source/mongo/services/completionItemProvider.ts @@ -5,435 +5,588 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable { - const text = this.textDocument.getText(); - const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1)); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document)) - .then(list => { - return list!.items.map(item => { - const startPositionOffset = document.offsetAt(item.textEdit!.range.start); - const endPositionOffset = document.offsetAt(item.textEdit!.range.end); - item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset)); - return item; - }); - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))]) - .then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range - }, - kind: CompletionItemKind.Keyword, - label: 'db' - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range) - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then(collections => { - return collections.map(collection => ({ - textEdit: { - newText: collection.collectionName, - range - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}` - })); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range) - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}` - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } - +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ErrorNode } from "antlr4ts/tree/ErrorNode"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Db } from "mongodb"; +import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; +import { + CompletionItem, + CompletionItemKind, + Position, + Range, +} from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { mongoLexer } from "./../grammar/mongoLexer"; +import * as mongoParser from "./../grammar/mongoParser"; +import { MongoVisitor } from "./../grammar/visitors"; +import { SchemaService } from "./schemaService"; + +export class CompletionItemsVisitor extends MongoVisitor< + Promise +> { + private at: Position; + + constructor( + private textDocument: TextDocument, + private db: Db, + private offset: number, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + super(); + this.at = this.textDocument.positionAt(this.offset); + } + + public visitCommands( + ctx: mongoParser.CommandsContext + ): Promise { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(ctx)) + ); + } + + public visitEmptyCommand( + ctx: mongoParser.EmptyCommandContext + ): Promise { + return this.thenable( + this.createDbKeywordCompletion(this.createRangeAfter(ctx)) + ); + } + + public visitCommand( + ctx: mongoParser.CommandContext + ): Promise { + if (ctx.childCount === 0) { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(ctx)) + ); + } + + const lastTerminalNode = this.getLastTerminalNode(ctx); + if (lastTerminalNode) { + return this.getCompletionItemsFromTerminalNode(lastTerminalNode); + } + return this.thenable(); + } + + public visitCollection( + ctx: mongoParser.CollectionContext + ): Promise { + return Promise.all([ + this.createCollectionCompletions(this.createRange(ctx)), + this.createDbFunctionCompletions(this.createRange(ctx)), + ]).then(([collectionCompletions, dbFunctionCompletions]) => [ + ...collectionCompletions, + ...dbFunctionCompletions, + ]); + } + + public visitFunctionCall( + ctx: mongoParser.FunctionCallContext + ): Promise { + const previousNode = this.getPreviousNode(ctx); + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode(previousNode); + } + return this.thenable(); + } + + public visitArguments( + ctx: mongoParser.ArgumentsContext + ): Promise { + const terminalNode = this.getLastTerminalNode(ctx); + if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { + return this.thenable( + this.createDbKeywordCompletion( + this.createRangeAfter(terminalNode) + ) + ); + } + return this.thenable(); + } + + public visitArgument( + ctx: mongoParser.ArgumentContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitObjectLiteral( + ctx: mongoParser.ObjectLiteralContext + ): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if ( + [ + "find", + "findOne", + "findOneAndDelete", + "findOneAndUpdate", + "findOneAndReplace", + "deleteOne", + "deleteMany", + "remove", + ].indexOf(functionName) !== -1 + ) { + return this.getArgumentCompletionItems( + this.schemaService.queryDocumentUri(collectionName), + collectionName, + ctx + ); + } + } + return ctx.parent!.accept(this); + } + + public visitArrayLiteral( + ctx: mongoParser.ArrayLiteralContext + ): Thenable { + const functionName = this.getFunctionName(ctx); + const collectionName = this.getCollectionName(ctx); + if (collectionName && functionName) { + if (["aggregate"].indexOf(functionName) !== -1) { + return this.getArgumentCompletionItems( + this.schemaService.aggregateDocumentUri(collectionName), + collectionName, + ctx + ); + } + } + return ctx.parent!.accept(this); + } + + public visitElementList( + ctx: mongoParser.ElementListContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyNameAndValueList( + ctx: mongoParser.PropertyNameAndValueListContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyAssignment( + ctx: mongoParser.PropertyAssignmentContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyValue( + ctx: mongoParser.PropertyValueContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitPropertyName( + ctx: mongoParser.PropertyNameContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitLiteral( + ctx: mongoParser.LiteralContext + ): Promise { + return ctx.parent!.accept(this); + } + + public visitTerminal(ctx: TerminalNode): Promise { + return ctx.parent!.accept(this); + } + + public visitErrorNode(ctx: ErrorNode): Promise { + return ctx.parent!.accept(this); + } + + private getArgumentCompletionItems( + documentUri: string, + _collectionName: string, + ctx: ParserRuleContext + ): Thenable { + const text = this.textDocument.getText(); + const document = TextDocument.create( + documentUri, + "json", + 1, + text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1) + ); + const positionOffset = this.textDocument.offsetAt(this.at); + const contextOffset = ctx.start.startIndex; + const position = document.positionAt(positionOffset - contextOffset); + return this.jsonLanguageService + .doComplete( + document, + position, + this.jsonLanguageService.parseJSONDocument(document) + ) + .then((list) => { + return list!.items.map((item) => { + const startPositionOffset = document.offsetAt( + item.textEdit!.range.start + ); + const endPositionOffset = document.offsetAt( + item.textEdit!.range.end + ); + item.textEdit!.range = Range.create( + this.textDocument.positionAt( + startPositionOffset + contextOffset + ), + this.textDocument.positionAt( + contextOffset + endPositionOffset + ) + ); + return item; + }); + }); + } + + private getFunctionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + return (parent)._FUNCTION_NAME.text!; + } + + private getCollectionName(ctx: ParseTree): string { + let parent = ctx.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { + return null!; + } + parent = parent.parent!; + if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { + return null!; + } + let previousNode = this.getPreviousNode(parent); + if ( + previousNode && + previousNode instanceof TerminalNode && + previousNode.symbol.type === mongoLexer.DOT + ) { + previousNode = this.getPreviousNode(previousNode); + if ( + previousNode && + previousNode instanceof mongoParser.CollectionContext + ) { + return previousNode.text; + } + } + return null!; + } + + private getCompletionItemsFromTerminalNode( + node: TerminalNode + ): Promise { + if (node._symbol.type === mongoParser.mongoParser.DB) { + return this.thenable( + this.createDbKeywordCompletion(this.createRange(node)) + ); + } + if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { + return this.thenable( + this.createDbKeywordCompletion(this.createRangeAfter(node)) + ); + } + if (node._symbol.type === mongoParser.mongoParser.DOT) { + const previousNode = this.getPreviousNode(node); + if (previousNode && previousNode instanceof TerminalNode) { + if (previousNode._symbol.type === mongoParser.mongoParser.DB) { + return Promise.all([ + this.createCollectionCompletions( + this.createRangeAfter(node) + ), + this.createDbFunctionCompletions( + this.createRangeAfter(node) + ), + ]).then( + ([collectionCompletions, dbFunctionCompletions]) => [ + ...collectionCompletions, + ...dbFunctionCompletions, + ] + ); + } + } + if (previousNode instanceof mongoParser.CollectionContext) { + return this.createCollectionFunctionsCompletions( + this.createRangeAfter(node) + ); + } + } + if (node instanceof ErrorNode) { + const previousNode = this.getPreviousNode(node); + if (previousNode) { + if (previousNode instanceof TerminalNode) { + return this.getCompletionItemsFromTerminalNode( + previousNode + ); + } + return previousNode.accept(this); + } + } + return this.thenable(); + } + + private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { + return ctx.children ? ctx.children + .slice() + .reverse() + .filter( + (node) => + node instanceof TerminalNode && + node.symbol.stopIndex > -1 && + node.symbol.stopIndex < this.offset + )[0] : null!; + } + + private getPreviousNode(node: ParseTree): ParseTree { + let previousNode: ParseTree = null!; + const parentNode = node.parent!; + for (let i = 0; i < parentNode.childCount; i++) { + const currentNode = parentNode.getChild(i); + if (currentNode === node) { + break; + } + previousNode = currentNode; + } + return previousNode; + } + + private createDbKeywordCompletion(range: Range): CompletionItem { + return { + textEdit: { + newText: "db", + range, + }, + kind: CompletionItemKind.Keyword, + label: "db", + }; + } + + private createDbFunctionCompletions( + range: Range + ): Promise { + return this.thenable( + this.createFunctionCompletion("adminCommand", range), + this.createFunctionCompletion("auth", range), + this.createFunctionCompletion("cloneDatabase", range), + this.createFunctionCompletion("commandHelp", range), + this.createFunctionCompletion("copyDatabase", range), + this.createFunctionCompletion("createCollection", range), + this.createFunctionCompletion("createView", range), + this.createFunctionCompletion("createUser", range), + this.createFunctionCompletion("currentOp", range), + this.createFunctionCompletion("dropDatabase", range), + this.createFunctionCompletion("eval", range), + this.createFunctionCompletion("fsyncLock", range), + this.createFunctionCompletion("fsyncUnLock", range), + this.createFunctionCompletion("getCollection", range), + this.createFunctionCompletion("getCollectionInfos", range), + this.createFunctionCompletion("getCollectionNames", range), + this.createFunctionCompletion("getLastError", range), + this.createFunctionCompletion("getLastErrorObj", range), + this.createFunctionCompletion("getLogComponents", range), + this.createFunctionCompletion("getMongo", range), + this.createFunctionCompletion("getName", range), + this.createFunctionCompletion("getPrevError", range), + this.createFunctionCompletion("getProfilingLevel", range), + this.createFunctionCompletion("getProfilingStatus", range), + this.createFunctionCompletion("getReplicationInfo", range), + this.createFunctionCompletion("getSiblingDB", range), + this.createFunctionCompletion("getWriteConcern", range), + this.createFunctionCompletion("hostInfo", range), + this.createFunctionCompletion("isMaster", range), + this.createFunctionCompletion("killOp", range), + this.createFunctionCompletion("listCommands", range), + this.createFunctionCompletion("loadServerScripts", range), + this.createFunctionCompletion("logout", range), + this.createFunctionCompletion("printCollectionStats", range), + this.createFunctionCompletion("printReplicationInfo", range), + this.createFunctionCompletion("printShardingStatus", range), + this.createFunctionCompletion("printSlaveReplicationInfo", range), + this.createFunctionCompletion("dropUser", range), + this.createFunctionCompletion("repairDatabase", range), + this.createFunctionCompletion("runCommand", range), + this.createFunctionCompletion("serverStatus", range), + this.createFunctionCompletion("setLogLevel", range), + this.createFunctionCompletion("setProfilingLevel", range), + this.createFunctionCompletion("setWriteConcern", range), + this.createFunctionCompletion("unsetWriteConcern", range), + this.createFunctionCompletion("setVerboseShell", range), + this.createFunctionCompletion("shotdownServer", range), + this.createFunctionCompletion("stats", range), + this.createFunctionCompletion("version", range) + ); + } + + private createCollectionCompletions( + range: Range + ): Promise { + if (this.db) { + return >( + this.db.collections().then((collections) => { + return collections.map( + (collection) => + { + textEdit: { + newText: collection.collectionName, + range, + }, + label: collection.collectionName, + kind: CompletionItemKind.Property, + filterText: collection.collectionName, + sortText: `1:${collection.collectionName}`, + } + ); + }) + ); + } + return Promise.resolve([]); + } + + private createCollectionFunctionsCompletions( + range: Range + ): Promise { + return this.thenable( + this.createFunctionCompletion("bulkWrite", range), + this.createFunctionCompletion("count", range), + this.createFunctionCompletion("copyTo", range), + this.createFunctionCompletion("convertToCapped", range), + this.createFunctionCompletion("createIndex", range), + this.createFunctionCompletion("createIndexes", range), + this.createFunctionCompletion("dataSize", range), + this.createFunctionCompletion("deleteOne", range), + this.createFunctionCompletion("deleteMany", range), + this.createFunctionCompletion("distinct", range), + this.createFunctionCompletion("drop", range), + this.createFunctionCompletion("dropIndex", range), + this.createFunctionCompletion("dropIndexes", range), + this.createFunctionCompletion("ensureIndex", range), + this.createFunctionCompletion("explain", range), + this.createFunctionCompletion("reIndex", range), + this.createFunctionCompletion("find", range), + this.createFunctionCompletion("findOne", range), + this.createFunctionCompletion("findOneAndDelete", range), + this.createFunctionCompletion("findOneAndReplace", range), + this.createFunctionCompletion("findOneAndUpdate", range), + this.createFunctionCompletion("getDB", range), + this.createFunctionCompletion("getPlanCache", range), + this.createFunctionCompletion("getIndexes", range), + this.createFunctionCompletion("group", range), + this.createFunctionCompletion("insert", range), + this.createFunctionCompletion("insertOne", range), + this.createFunctionCompletion("insertMany", range), + this.createFunctionCompletion("mapReduce", range), + this.createFunctionCompletion("aggregate", range), + this.createFunctionCompletion("remove", range), + this.createFunctionCompletion("replaceOne", range), + this.createFunctionCompletion("renameCollection", range), + this.createFunctionCompletion("runCommand", range), + this.createFunctionCompletion("save", range), + this.createFunctionCompletion("stats", range), + this.createFunctionCompletion("storageSize", range), + this.createFunctionCompletion("totalIndexSize", range), + this.createFunctionCompletion("update", range), + this.createFunctionCompletion("updateOne", range), + this.createFunctionCompletion("updateMany", range), + this.createFunctionCompletion("validate", range), + this.createFunctionCompletion("getShardVersion", range), + this.createFunctionCompletion("getShardDistribution", range), + this.createFunctionCompletion("getSplitKeysForChunks", range), + this.createFunctionCompletion("getWriteConcern", range), + this.createFunctionCompletion("setWriteConcern", range), + this.createFunctionCompletion("unsetWriteConcern", range), + this.createFunctionCompletion("latencyStats", range) + ); + } + + private createFunctionCompletion( + label: string, + range: Range + ): CompletionItem { + return { + textEdit: { + newText: label, + range, + }, + kind: CompletionItemKind.Function, + label, + sortText: `2:${label}`, + }; + } + + private createRange(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + const startToken = parserRuleContext.start; + let stopToken = parserRuleContext.stop; + if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { + stopToken = startToken; + } + + const stop = stopToken.stopIndex; + return this._createRange(startToken.startIndex, stop); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange( + parserRuleContext.symbol.startIndex, + parserRuleContext.symbol.stopIndex + ); + } + + return null!; + } + + private createRangeAfter(parserRuleContext: ParseTree): Range { + if (parserRuleContext instanceof ParserRuleContext) { + let stopToken = parserRuleContext.stop; + if (!stopToken) { + stopToken = parserRuleContext.start; + } + + const stop = stopToken.stopIndex; + return this._createRange(stop + 1, stop + 1); + } + + if (parserRuleContext instanceof TerminalNode) { + return this._createRange( + parserRuleContext.symbol.stopIndex + 1, + parserRuleContext.symbol.stopIndex + 1 + ); + } + + //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want + // to introduce a regression bug. + return null!; + } + + private _createRange(start: number, end: number): Range { + const endPosition = this.textDocument.positionAt(end); + if (endPosition.line < this.at.line) { + return Range.create(Position.create(this.at.line, 0), this.at); + } + const startPosition = this.textDocument.positionAt(start); + return Range.create(startPosition, endPosition); + } + + private thenable( + ...completionItems: CompletionItem[] + ): Promise { + return Promise.resolve(completionItems || []); + } } diff --git a/Source/mongo/services/languageService.ts b/Source/mongo/services/languageService.ts index 83b1b594e..7629c9258 100644 --- a/Source/mongo/services/languageService.ts +++ b/Source/mongo/services/languageService.ts @@ -5,86 +5,119 @@ // NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) -import { Db } from 'mongodb'; -import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice'; -import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; +import { Db } from "mongodb"; +import { + getLanguageService, + LanguageService as JsonLanguageService, + SchemaConfiguration, +} from "vscode-json-languageservice"; +import { + CompletionItem, + IConnection, + InitializeParams, + InitializeResult, + TextDocumentPositionParams, + TextDocuments, + TextDocumentSyncKind, +} from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { IConnectionParams } from "./IConnectionParams"; +import { MongoScriptDocumentManager } from "./mongoScript"; +import { SchemaService } from "./schemaService"; export class LanguageService { - - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db; - - private jsonLanguageService: JsonLanguageService; - private schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor(connection: IConnection) { - - this.schemaService = new SchemaService(); - - this.textDocuments.listen(connection); - // After the server has started the client sends an initilize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] } - } - }; - }); - - connection.onCompletion(textDocumentPosition => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent) - .then(account => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db) - .then(schemas => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.db = null!; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: uri => this.schemaService.resolveSchema(uri), - contributions: [] - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument!, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas - }); - } + private textDocuments: TextDocuments = new TextDocuments( + TextDocument + ); + private readonly mongoDocumentsManager: MongoScriptDocumentManager; + private db: Db; + + private jsonLanguageService: JsonLanguageService; + private schemaService: SchemaService; + private schemas: SchemaConfiguration[]; + + constructor(connection: IConnection) { + this.schemaService = new SchemaService(); + + this.textDocuments.listen(connection); + // After the server has started the client sends an initilize request. The server receives + // in the passed params the rootPath of the workspace plus the client capabilities. + connection.onInitialize( + (_params: InitializeParams): InitializeResult => { + return { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode + completionProvider: { triggerCharacters: ["."] }, + }, + }; + } + ); + + connection.onCompletion((textDocumentPosition) => { + return this.provideCompletionItems(textDocumentPosition); + }); + + connection.onRequest( + "connect", + (connectionParams: IConnectionParams) => { + void connectToMongoClient( + connectionParams.connectionString, + connectionParams.extensionUserAgent + ).then((account) => { + this.db = account.db(connectionParams.databaseName); + void this.schemaService + .registerSchemas(this.db) + .then((schemas) => { + this.configureSchemas(schemas); + }); + }); + } + ); + + connection.onRequest("disconnect", () => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.db = null!; + for (const schema of this.schemas) { + this.jsonLanguageService.resetSchema(schema.uri); + } + }); + + this.jsonLanguageService = getLanguageService({ + schemaRequestService: (uri) => + this.schemaService.resolveSchema(uri), + contributions: [], + }); + + this.mongoDocumentsManager = new MongoScriptDocumentManager( + this.schemaService, + this.jsonLanguageService + ); + } + + public provideCompletionItems( + positionParams: TextDocumentPositionParams + ): Promise { + const textDocument = this.textDocuments.get( + positionParams.textDocument.uri + ); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const mongoScriptDocument = this.mongoDocumentsManager.getDocument( + textDocument!, + this.db + ); + return mongoScriptDocument.provideCompletionItemsAt( + positionParams.position + ); + } + + public resetSchema(uri: string): void { + this.jsonLanguageService.resetSchema(uri); + } + + public configureSchemas(schemas: SchemaConfiguration[]): void { + this.jsonLanguageService.configure({ + schemas, + }); + } } diff --git a/Source/mongo/services/mongoScript.ts b/Source/mongo/services/mongoScript.ts index 8d4c85398..4d5cb89dd 100644 --- a/Source/mongo/services/mongoScript.ts +++ b/Source/mongo/services/mongoScript.ts @@ -2,100 +2,133 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { Db } from 'mongodb'; -import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItem, Position } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from './../grammar/mongoLexer'; -import * as mongoParser from './../grammar/mongoParser'; -import { MongoVisitor } from './../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { SchemaService } from './schemaService'; +import { ANTLRInputStream as InputStream } from "antlr4ts/ANTLRInputStream"; +import { CommonTokenStream } from "antlr4ts/CommonTokenStream"; +import { Interval } from "antlr4ts/misc/Interval"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ParseTree } from "antlr4ts/tree/ParseTree"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Db } from "mongodb"; +import { LanguageService as JsonLanguageService } from "vscode-json-languageservice"; +import { CompletionItem, Position } from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; +import { mongoLexer } from "./../grammar/mongoLexer"; +import * as mongoParser from "./../grammar/mongoParser"; +import { MongoVisitor } from "./../grammar/visitors"; +import { CompletionItemsVisitor } from "./completionItemProvider"; +import { SchemaService } from "./schemaService"; export class MongoScriptDocumentManager { + constructor( + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) {} - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - } - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } + public getDocument( + textDocument: TextDocument, + db: Db + ): MongoScriptDocument { + return new MongoScriptDocument( + textDocument, + db, + this.schemaService, + this.jsonLanguageService + ); + } } export class MongoScriptDocument { + private readonly _lexer: mongoLexer; - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } + constructor( + private textDocument: TextDocument, + private db: Db, + private schemaService: SchemaService, + private jsonLanguageService: JsonLanguageService + ) { + this._lexer = new mongoLexer(new InputStream(textDocument.getText())); + this._lexer.removeErrorListeners(); + } - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); + public provideCompletionItemsAt( + position: Position + ): Promise { + const parser = new mongoParser.mongoParser( + new CommonTokenStream(this._lexer) + ); + parser.removeErrorListeners(); - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode); - } - return Promise.resolve([]); - } + const offset = this.textDocument.offsetAt(position); + const lastNode = new NodeFinder(offset).visit(parser.commands()); + if (lastNode) { + return new CompletionItemsVisitor( + this.textDocument, + this.db, + offset, + this.schemaService, + this.jsonLanguageService + ).visit(lastNode); + } + return Promise.resolve([]); + } } class NodeFinder extends MongoVisitor { + constructor(private offset: number) { + super(); + } - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return null!; - } + protected defaultResult(ctx: ParseTree): ParseTree { + if (ctx instanceof ParserRuleContext) { + const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; + if (stop < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + if (ctx instanceof TerminalNode) { + if (ctx.symbol.stopIndex < this.offset) { + return ctx; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return null!; + } - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (aggregate).symbol.startIndex; - const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (aggregate).symbol.stopIndex; - const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (nextResult).symbol.startIndex; - const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (nextResult).symbol.stopIndex; + protected aggregateResult( + aggregate: ParseTree, + nextResult: ParseTree + ): ParseTree { + if (aggregate && nextResult) { + const aggregateStart = + aggregate instanceof ParserRuleContext + ? aggregate.start.startIndex + : (aggregate).symbol.startIndex; + const aggregateStop = + aggregate instanceof ParserRuleContext + ? aggregate.start.stopIndex + : (aggregate).symbol.stopIndex; + const nextResultStart = + nextResult instanceof ParserRuleContext + ? nextResult.start.startIndex + : (nextResult).symbol.startIndex; + const nextResultStop = + nextResult instanceof ParserRuleContext + ? nextResult.start.stopIndex + : (nextResult).symbol.stopIndex; - if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } + if ( + Interval.of(aggregateStart, aggregateStop).properlyContains( + Interval.of(nextResultStart, nextResultStop) + ) + ) { + return aggregate; + } + return nextResult; + } + return nextResult ? nextResult : aggregate; + } } diff --git a/Source/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts index cf70e8cde..acb195725 100644 --- a/Source/mongo/services/schemaService.ts +++ b/Source/mongo/services/schemaService.ts @@ -5,624 +5,726 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */ -import { Cursor, Db } from 'mongodb'; -import { SchemaConfiguration } from 'vscode-json-languageservice'; +import { Cursor, Db } from "mongodb"; +import { SchemaConfiguration } from "vscode-json-languageservice"; // eslint-disable-next-line import/no-internal-modules -import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema'; +import { JSONSchema } from "vscode-json-languageservice/lib/umd/jsonSchema"; export class SchemaService { - - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections() - .then(collections => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push(...[{ - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)] - }, { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)] - }]); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length)) - .then(sch => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {} - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)) - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document); - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - for (const property of Object.keys(document)) { - if (!parent && - ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'] - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase' - }, - $language: { - type: 'string', - description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming' - }, - $caseSensitive: { - type: 'boolean', - description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index' - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index` - } - }, - required: ['$search'] - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system` - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate' - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri - } - }; - schema.properties!.$and = { - type: 'array', - description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri - } - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri - } - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: {} - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value' - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value' - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value' - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value' - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value' - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value' - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array' - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array' - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field' - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type' - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0] - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression' - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type' - }, - coordinates: { - type: 'array' - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string' - }, - properties: { - type: 'object' - } - } - } - } - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array' - }, - $polygon: { - type: 'array' - }, - $center: { - type: 'array' - }, - $centerSphere: { - type: 'array' - } - } - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema - } - }; - expressionSchema.properties.$near = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number' - }, - $minDistance: { - type: 'number' - } - } - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query' - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size' - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1' - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1' - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0' - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0' - }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - properties: { ...expressionSchema.properties } - }; - schema.properties!.$elemMatch = { - type: 'object' - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view' - } - } - - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri - } - } - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'] - } - }, - additionalProperties: { - type: 'object' - } - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline' - } - } - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document' - } - } - }); - return { - type: 'object', - oneOf: schemas - }; - } - - private readNext(result: any[], cursor: Cursor, batchSize: number, callback: (result: any[]) => void): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then(hasNext => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then(doc => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } - + private _db: Db; + private _schemasCache: Map = new Map(); + + public registerSchemas(db: Db): Thenable { + this._db = db; + this._schemasCache.clear(); + return this._db.collections().then((collections) => { + const schemas: SchemaConfiguration[] = []; + for (const collection of collections) { + schemas.push( + ...[ + { + uri: this.queryCollectionSchema( + collection.collectionName + ), + fileMatch: [ + this.queryDocumentUri( + collection.collectionName + ), + ], + }, + { + uri: this.aggregateCollectionSchema( + collection.collectionName + ), + fileMatch: [ + this.aggregateDocumentUri( + collection.collectionName + ), + ], + }, + ] + ); + } + return schemas; + }); + } + + public queryCollectionSchema(collectionName: string): string { + return "mongo://query/" + collectionName + ".schema"; + } + + public aggregateCollectionSchema(collectionName: string): string { + return "mongo://aggregate/" + collectionName + ".schema"; + } + + public queryDocumentUri(collectionName: string): string { + return "mongo://query/" + collectionName + ".json"; + } + + public aggregateDocumentUri(collectionName: string): string { + return "mongo://aggregate/" + collectionName + ".json"; + } + + public resolveSchema(uri: string): Thenable { + const schema = this._schemasCache.get(uri); + if (schema) { + return Promise.resolve(schema); + } + if (uri.startsWith("mongo://query/")) { + return this._resolveQueryCollectionSchema( + uri.substring( + "mongo://query/".length, + uri.length - ".schema".length + ), + uri + ).then((sch) => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + if (uri.startsWith("mongo://aggregate/")) { + return this._resolveAggregateCollectionSchema( + uri.substring( + "mongo://aggregate/".length, + uri.length - ".schema".length + ) + ).then((sch) => { + this._schemasCache.set(uri, sch); + return sch; + }); + } + return Promise.resolve(""); + } + + private _resolveQueryCollectionSchema( + collectionName: string, + schemaUri: string + ): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (result) => { + const schema: JSONSchema = { + type: "object", + properties: {}, + }; + for (const document of result) { + this.setSchemaForDocument(null!, document, schema); + } + this.setGlobalOperatorProperties(schema); + this.setLogicalOperatorProperties(schema, schemaUri); + resolve(JSON.stringify(schema)); + }); + }); + } + + private _resolveAggregateCollectionSchema( + collectionName: string + ): Thenable { + const collection = this._db.collection(collectionName); + const cursor = collection.find(); + return new Promise((resolve, _reject) => { + this.readNext([], cursor, 10, (_result) => { + const schema: JSONSchema = { + type: "array", + items: this.getAggregateStagePropertiesSchema( + this.queryCollectionSchema(collectionName) + ), + }; + resolve(JSON.stringify(schema)); + }); + }); + } + + private getMongoDocumentType(document: any): string { + return Array.isArray(document) + ? "array" + : document === null + ? "null" + : typeof document; + } + + private setSchemaForDocument( + parent: string, + document: any, + schema: JSONSchema + ): void { + if (this.getMongoDocumentType(document) === "object") { + for (const property of Object.keys(document)) { + if (!parent && ["_id"].indexOf(property) !== -1) { + continue; + } + this.setSchemaForDocumentProperty( + parent, + property, + document, + schema + ); + } + } + } + + private setSchemaForDocumentProperty( + parent: string, + property: string, + document: any, + schema: JSONSchema + ): void { + const scopedProperty = parent ? `${parent}.${property}` : property; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const value = document[property]; + const type = this.getMongoDocumentType(value); + + const propertySchema: JSONSchema = { + type: [type, "object"], + }; + this.setOperatorProperties(type, propertySchema); + schema.properties![scopedProperty] = propertySchema; + + if (type === "object") { + this.setSchemaForDocument(scopedProperty, value, schema); + } + + if (type === "array") { + for (const v of value) { + this.setSchemaForDocument(scopedProperty, v, schema); + } + } + } + + private setGlobalOperatorProperties(schema: JSONSchema): void { + schema.properties!.$text = { + type: "object", + description: "Performs text search", + properties: { + $search: { + type: "string", + description: + "A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase", + }, + $language: { + type: "string", + description: + 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming', + }, + $caseSensitive: { + type: "boolean", + description: + "Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index", + }, + $diacriticSensitive: { + type: "boolean", + description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index +Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`, + }, + }, + required: ["$search"], + }; + + schema.properties!.$where = { + type: "string", + description: `Matches documents that satisfy a JavaScript expression. +Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`, + }; + schema.properties!.$comment = { + type: "string", + description: "Adds a comment to a query predicate", + }; + } + + private setLogicalOperatorProperties( + schema: JSONSchema, + schemaUri: string + ): void { + schema.properties!.$or = { + type: "array", + description: + "Joins query clauses with a logical OR returns all documents that match the conditions of either clause", + items: { + $ref: schemaUri, + }, + }; + schema.properties!.$and = { + type: "array", + description: + "Joins query clauses with a logical AND returns all documents that match the conditions of both clauses", + items: { + $ref: schemaUri, + }, + }; + schema.properties!.$nor = { + type: "array", + description: + "Joins query clauses with a logical NOR returns all documents that fail to match both clauses", + items: { + $ref: schemaUri, + }, + }; + } + + private setOperatorProperties(type: string, schema: JSONSchema): void { + if (!schema.properties) { + schema.properties = {}; + } + + const expressionSchema = { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: {}, + }; + // Comparison operators + expressionSchema.properties.$eq = { + type: type, + description: "Matches values that are equal to a specified value", + }; + expressionSchema.properties.$gt = { + type: type, + description: + "Matches values that are greater than a specified value", + }; + expressionSchema.properties.$gte = { + type: type, + description: + "Matches values that are greater than or equal to a specified value", + }; + expressionSchema.properties.$lt = { + type: type, + description: "Matches values that are less than a specified value", + }; + expressionSchema.properties.$lte = { + type: type, + description: + "Matches values that are less than or equal to a specified value", + }; + expressionSchema.properties.$ne = { + type: type, + description: + "Matches all values that are not equal to a specified value", + }; + expressionSchema.properties.$in = { + type: "array", + description: "Matches any of the values specified in an array", + }; + expressionSchema.properties.$nin = { + type: "array", + description: "Matches none of the values specified in an array", + }; + + // Element operators + expressionSchema.properties.$exists = { + type: "boolean", + description: "Matches documents that have the specified field", + }; + expressionSchema.properties.$type = { + type: "string", + description: + "Selects documents if a field is of the specified type", + }; + + // Evaluation operators + expressionSchema.properties.$mod = { + type: "array", + description: + "Performs a modulo operation on the value of a field and selects documents with a specified result", + maxItems: 2, + default: [2, 0], + }; + expressionSchema.properties.$regex = { + type: "string", + description: + "Selects documents where values match a specified regular expression", + }; + + // Geospatial + const geometryPropertySchema: JSONSchema = { + type: "object", + properties: { + type: { + type: "string", + default: "GeoJSON object type", + }, + coordinates: { + type: "array", + }, + crs: { + type: "object", + properties: { + type: { + type: "string", + }, + properties: { + type: "object", + }, + }, + }, + }, + }; + expressionSchema.properties.$geoWithin = { + type: "object", + description: + "Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin", + properties: { + $geometry: geometryPropertySchema, + $box: { + type: "array", + }, + $polygon: { + type: "array", + }, + $center: { + type: "array", + }, + $centerSphere: { + type: "array", + }, + }, + }; + expressionSchema.properties.$geoIntersects = { + type: "object", + description: + "Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects", + properties: { + $geometry: geometryPropertySchema, + }, + }; + expressionSchema.properties.$near = { + type: "object", + description: + "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: "number", + }, + $minDistance: { + type: "number", + }, + }, + }; + expressionSchema.properties.$nearSphere = { + type: "object", + description: + "Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near", + properties: { + $geometry: geometryPropertySchema, + $maxDistance: { + type: "number", + }, + $minDistance: { + type: "number", + }, + }, + }; + + // Array operatos + if (type === "array") { + expressionSchema.properties.$all = { + type: "array", + description: + "Matches arrays that contain all elements specified in the query", + }; + expressionSchema.properties.$size = { + type: "number", + description: + "Selects documents if the array field is a specified size", + }; + } + + // Bit operators + expressionSchema.properties.$bitsAllSet = { + type: "array", + description: + "Matches numeric or binary values in which a set of bit positions all have a value of 1", + }; + expressionSchema.properties.$bitsAnySet = { + type: "array", + description: + "Matches numeric or binary values in which any bit from a set of bit positions has a value of 1", + }; + expressionSchema.properties.$bitsAllClear = { + type: "array", + description: + "Matches numeric or binary values in which a set of bit positions all have a value of 0", + }; + expressionSchema.properties.$bitsAnyClear = { + type: "array", + description: + "Matches numeric or binary values in which any bit from a set of bit positions has a value of 0", + }; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + schema.properties = { ...expressionSchema.properties }; + schema.properties!.$not = { + type: "object", + description: + "Inverts the effect of a query expression and returns documents that do not match the query expression", + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + properties: { ...expressionSchema.properties }, + }; + schema.properties!.$elemMatch = { + type: "object", + }; + } + + private getAggregateStagePropertiesSchema( + querySchemaUri: string + ): JSONSchema { + const schemas: JSONSchema[] = []; + schemas.push({ + type: "object", + properties: { + $collStats: { + type: "object", + description: + "Returns statistics regarding a collection or view", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $project: { + type: "object", + description: + "Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $match: { + type: "object", + description: + "Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)", + $ref: querySchemaUri, + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $redact: { + type: "object", + description: + "Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $limit: { + type: "object", + description: + "Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $skip: { + type: "object", + description: + "Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $unwind: { + type: "object", + description: + "Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $group: { + type: "object", + description: + "Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.", + properties: { + _id: { + type: ["string", "object"], + }, + }, + additionalProperties: { + type: "object", + }, + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sample: { + type: "object", + description: + "Randomly selects the specified number of documents from its input", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sort: { + type: "object", + description: + "Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $geoNear: { + type: "object", + description: + "Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $lookup: { + type: "object", + description: + "Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $out: { + type: "object", + description: + "Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $indexStats: { + type: "object", + description: + "Returns statistics regarding the use of each index for the collection", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $facet: { + type: "object", + description: + "Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $bucket: { + type: "object", + description: + "Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $bucketAuto: { + type: "object", + description: + "Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $sortByCount: { + type: "object", + description: + "Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $addFields: { + type: "object", + description: + "Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $replaceRoot: { + type: "object", + description: + "Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $count: { + type: "object", + description: + "Returns a count of the number of documents at this stage of the aggregation pipeline", + }, + }, + }); + schemas.push({ + type: "object", + properties: { + $graphLookup: { + type: "object", + description: + "Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document", + }, + }, + }); + return { + type: "object", + oneOf: schemas, + }; + } + + private readNext( + result: any[], + cursor: Cursor, + batchSize: number, + callback: (result: any[]) => void + ): void { + if (result.length === batchSize) { + callback(result); + return; + } + + void cursor.hasNext().then((hasNext) => { + if (!hasNext) { + callback(result); + return; + } + + void cursor.next().then((doc) => { + result.push(doc); + this.readNext(result, cursor, batchSize, callback); + }); + }); + } } diff --git a/Source/mongo/setConnectedNode.ts b/Source/mongo/setConnectedNode.ts index f5680d09d..bcb8e95e1 100644 --- a/Source/mongo/setConnectedNode.ts +++ b/Source/mongo/setConnectedNode.ts @@ -6,8 +6,10 @@ import { ext } from "../extensionVariables"; import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem"; -export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void { - ext.connectedMongoDB = node; - const dbName = node && node.label; - ext.mongoCodeLensProvider.setConnectedDatabase(dbName); +export function setConnectedNode( + node: MongoDatabaseTreeItem | undefined +): void { + ext.connectedMongoDB = node; + const dbName = node && node.label; + ext.mongoCodeLensProvider.setConnectedDatabase(dbName); } diff --git a/Source/mongo/tree/IMongoTreeRoot.ts b/Source/mongo/tree/IMongoTreeRoot.ts index d9b68980d..262e03876 100644 --- a/Source/mongo/tree/IMongoTreeRoot.ts +++ b/Source/mongo/tree/IMongoTreeRoot.ts @@ -1,9 +1,8 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ export interface IMongoTreeRoot { - isEmulator: boolean | undefined; + isEmulator: boolean | undefined; } diff --git a/Source/mongo/tree/MongoAccountTreeItem.ts b/Source/mongo/tree/MongoAccountTreeItem.ts index baa870c23..2f4621afb 100644 --- a/Source/mongo/tree/MongoAccountTreeItem.ts +++ b/Source/mongo/tree/MongoAccountTreeItem.ts @@ -3,138 +3,191 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models'; -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; -import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext'; -import { getThemeAgnosticIconPath, Links, testDb } from '../../constants'; -import { nonNullProp } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { getDatabaseNameFromConnectionString } from '../mongoConnectionStrings'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; -import { MongoDatabaseTreeItem } from './MongoDatabaseTreeItem'; -import { MongoDocumentTreeItem } from './MongoDocumentTreeItem'; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb/src/models"; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + AzExtTreeItem, + ICreateChildImplContext, + parseError, +} from "@microsoft/vscode-azext-utils"; +import { MongoClient } from "mongodb"; +import * as vscode from "vscode"; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; +import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; +import { getThemeAgnosticIconPath, Links, testDb } from "../../constants"; +import { nonNullProp } from "../../utils/nonNull"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { getDatabaseNameFromConnectionString } from "../mongoConnectionStrings"; +import { IMongoTreeRoot } from "./IMongoTreeRoot"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; +import { MongoDatabaseTreeItem } from "./MongoDatabaseTreeItem"; +import { MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; export class MongoAccountTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "cosmosDBMongoServer"; - public readonly contextValue: string = MongoAccountTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly label: string; - public readonly connectionString: string; - - private _root: IMongoTreeRoot; - - constructor(parent: AzExtParentTreeItem, id: string, label: string, connectionString: string, isEmulator: boolean | undefined, readonly databaseAccount?: DatabaseAccountGetResults) { - super(parent); - this.id = id; - this.label = label; - this.connectionString = connectionString; - this._root = { isEmulator }; - this.valuesToMask.push(connectionString); - } - - // overrides ISubscriptionContext with an object that also has Mongo info - public get root(): IMongoTreeRoot { - return this._root; - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('CosmosDBAccount.svg'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - let mongoClient: MongoClient | undefined; - try { - let databases: IDatabaseInfo[]; - - if (!this.connectionString) { - throw new Error('Missing connection string'); - } - - // Azure MongoDB accounts need to have the name passed in for private endpoints - mongoClient = await connectToMongoClient(this.connectionString, this.databaseAccount ? nonNullProp(this.databaseAccount, 'name') : appendExtensionUserAgent()); - - const databaseInConnectionString = getDatabaseNameFromConnectionString(this.connectionString); - if (databaseInConnectionString && !this.root.isEmulator) { // emulator violates the connection string format - // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) - databases = [{ - name: databaseInConnectionString, - empty: false - }]; - } else { - // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: { databases: IDatabaseInfo[] } = await mongoClient.db(testDb).admin().listDatabases(); - databases = result.databases; - } - return databases - .filter((database: IDatabaseInfo) => !(database.name && database.name.toLowerCase() === "admin" && database.empty)) // Filter out the 'admin' database if it's empty - .map(database => new MongoDatabaseTreeItem(this, nonNullProp(database, 'name'), this.connectionString)); - } catch (error) { - const message = parseError(error).message; - if (this._root.isEmulator && message.includes("ECONNREFUSED")) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; - } - throw error; - } - finally { - if (mongoClient) { - void mongoClient.close(); - } - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createMongoDatabase', - validateInput: validateDatabaseName - }); - context.showCreatingTreeItem(databaseName); - - return new MongoDatabaseTreeItem(this, databaseName, this.connectionString); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case MongoDatabaseTreeItem.contextValue: - case MongoCollectionTreeItem.contextValue: - case MongoDocumentTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public static contextValue: string = "cosmosDBMongoServer"; + public readonly contextValue: string = MongoAccountTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly label: string; + public readonly connectionString: string; + + private _root: IMongoTreeRoot; + + constructor( + parent: AzExtParentTreeItem, + id: string, + label: string, + connectionString: string, + isEmulator: boolean | undefined, + readonly databaseAccount?: DatabaseAccountGetResults + ) { + super(parent); + this.id = id; + this.label = label; + this.connectionString = connectionString; + this._root = { isEmulator }; + this.valuesToMask.push(connectionString); + } + + // overrides ISubscriptionContext with an object that also has Mongo info + public get root(): IMongoTreeRoot { + return this._root; + } + + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("CosmosDBAccount.svg"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + let mongoClient: MongoClient | undefined; + try { + let databases: IDatabaseInfo[]; + + if (!this.connectionString) { + throw new Error("Missing connection string"); + } + + // Azure MongoDB accounts need to have the name passed in for private endpoints + mongoClient = await connectToMongoClient( + this.connectionString, + this.databaseAccount + ? nonNullProp(this.databaseAccount, "name") + : appendExtensionUserAgent() + ); + + const databaseInConnectionString = + getDatabaseNameFromConnectionString(this.connectionString); + if (databaseInConnectionString && !this.root.isEmulator) { + // emulator violates the connection string format + // If the database is in the connection string, that's all we connect to (we might not even have permissions to list databases) + databases = [ + { + name: databaseInConnectionString, + empty: false, + }, + ]; + } else { + // https://mongodb.github.io/node-mongodb-native/3.1/api/index.html + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: { databases: IDatabaseInfo[] } = await mongoClient + .db(testDb) + .admin() + .listDatabases(); + databases = result.databases; + } + return databases + .filter( + (database: IDatabaseInfo) => + !( + database.name && + database.name.toLowerCase() === "admin" && + database.empty + ) + ) // Filter out the 'admin' database if it's empty + .map( + (database) => + new MongoDatabaseTreeItem( + this, + nonNullProp(database, "name"), + this.connectionString + ) + ); + } catch (error) { + const message = parseError(error).message; + if (this._root.isEmulator && message.includes("ECONNREFUSED")) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + error.message = `Unable to reach emulator. See ${Links.LocalConnectionDebuggingTips} for debugging tips.\n${message}`; + } + throw error; + } finally { + if (mongoClient) { + void mongoClient.close(); + } + } + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: "createMongoDatabase", + validateInput: validateDatabaseName, + }); + context.showCreatingTreeItem(databaseName); + + return new MongoDatabaseTreeItem( + this, + databaseName, + this.connectionString + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case MongoDatabaseTreeItem.contextValue: + case MongoCollectionTreeItem.contextValue: + case MongoDocumentTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } } -export function validateDatabaseName(database: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions - // "#?" are restricted characters for CosmosDB - MongoDB accounts - const min = 1; - const max = 63; - if (!database || database.length < min || database.length > max) { - return `Database name must be between ${min} and ${max} characters.`; - } - if (/[/\\. "$#?=]/.test(database)) { - return "Database name cannot contain these characters - `/\\. \"$#?=`"; - } - return undefined; +export function validateDatabaseName( + database: string +): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#naming-restrictions + // "#?" are restricted characters for CosmosDB - MongoDB accounts + const min = 1; + const max = 63; + if (!database || database.length < min || database.length > max) { + return `Database name must be between ${min} and ${max} characters.`; + } + if (/[/\\. "$#?=]/.test(database)) { + return 'Database name cannot contain these characters - `/\\. "$#?=`'; + } + return undefined; } export interface IDatabaseInfo { - name?: string; - empty?: boolean; + name?: string; + empty?: boolean; } diff --git a/Source/mongo/tree/MongoCollectionTreeItem.ts b/Source/mongo/tree/MongoCollectionTreeItem.ts index eca0c8d32..b4dd4f68f 100644 --- a/Source/mongo/tree/MongoCollectionTreeItem.ts +++ b/Source/mongo/tree/MongoCollectionTreeItem.ts @@ -5,316 +5,473 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as assert from 'assert'; -import { BulkWriteOpResultObject, Collection, CollectionInsertManyOptions, Cursor, DeleteWriteOpResultObject, InsertOneWriteOpResult, InsertWriteOpResult, MongoCountPreferences } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { nonNullValue } from '../../utils/nonNull'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { MongoCommand } from '../MongoCommand'; -import { IMongoDocument, MongoDocumentTreeItem } from './MongoDocumentTreeItem'; +import { + AzExtParentTreeItem, + AzExtTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as assert from "assert"; +import { + BulkWriteOpResultObject, + Collection, + CollectionInsertManyOptions, + Cursor, + DeleteWriteOpResultObject, + InsertOneWriteOpResult, + InsertWriteOpResult, + MongoCountPreferences, +} from "mongodb"; +import * as _ from "underscore"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { nonNullValue } from "../../utils/nonNull"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { getBatchSizeSetting } from "../../utils/workspacUtils"; +import { MongoCommand } from "../MongoCommand"; +import { IMongoDocument, MongoDocumentTreeItem } from "./MongoDocumentTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); type MongoFunction = (...args: ({} | {}[] | undefined)[]) => Thenable; type MongoDocument = { _id: string }; class FunctionDescriptor { - public constructor(public mongoFunction: MongoFunction, public text: string, public minShellArgs: number, public maxShellArgs: number, public maxHandledArgs: number) { - } + public constructor( + public mongoFunction: MongoFunction, + public text: string, + public minShellArgs: number, + public maxShellArgs: number, + public maxHandledArgs: number + ) {} } -export class MongoCollectionTreeItem extends AzExtParentTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoCollection"; - public readonly contextValue: string = MongoCollectionTreeItem.contextValue; - public readonly childTypeLabel: string = "Document"; - public readonly collection: Collection; - public parent: AzExtParentTreeItem; - public findArgs?: {}[]; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); - - private readonly _query: object | undefined; - private readonly _projection: object | undefined; - private _cursor: Cursor | undefined; - private _hasMoreChildren: boolean = true; - private _batchSize: number = getBatchSizeSetting(); - - constructor(parent: AzExtParentTreeItem, collection: Collection, findArgs?: {}[]) { - super(parent); - this.collection = collection; - this.findArgs = findArgs; - if (findArgs && findArgs.length) { - this._query = findArgs[0]; - this._projection = findArgs.length > 1 ? findArgs[1] : undefined; - } - ext.fileSystem.fireChangedEvent(this); - } - - public async writeFileContent(context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const documents: IMongoDocument[] = EJSON.parse(content); - const operations = documents.map((document) => { - return { - replaceOne: { - filter: { _id: document._id }, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - replacement: _.omit(document, '_id'), - upsert: false - } - }; - }); - - const result: BulkWriteOpResultObject = await this.collection.bulkWrite(operations); - ext.outputChannel.appendLog(`Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)`); - - // The current tree item may have been a temporary one used to execute a scrapbook command. - // We want to refresh children for this one _and_ the actual one in the tree (if it's different) - const nodeInTree: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); - const nodesToRefresh: MongoCollectionTreeItem[] = [this]; - if (nodeInTree && this !== nodeInTree) { - nodesToRefresh.push(nodeInTree); - } - - await Promise.all(nodesToRefresh.map(n => n.refreshChildren(context, documents))); - - if (nodeInTree && this !== nodeInTree) { - // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different - ext.fileSystem.fireChangedEvent(nodeInTree); - } - } - - public async getFileContent(context: IActionContext): Promise { - const children = await this.getCachedChildren(context); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(children.map(c => c.document), null, 2); - } - - public get id(): string { - return this.collection.collectionName; - } - - public get label(): string { - return this.collection.collectionName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('files'); - } - - public get filePath(): string { - return this.label + '-cosmos-collection.json'; - } - - public async refreshImpl(): Promise { - this._batchSize = getBatchSizeSetting(); - ext.fileSystem.fireChangedEvent(this); - } - - public async refreshChildren(context: IActionContext, docs: IMongoDocument[]): Promise { - const documentNodes = await this.getCachedChildren(context); - for (const doc of docs) { - const documentNode = documentNodes.find((node) => node.document._id.toString() === doc._id.toString()); - if (documentNode) { - documentNode.document = doc; - await documentNode.refresh(context); - } - } - } - - public hasMoreChildrenImpl(): boolean { - return this._hasMoreChildren; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache || this._cursor === undefined) { - this._cursor = this.collection.find(this._query).batchSize(this._batchSize); - if (this._projection) { - this._cursor = this._cursor.project(this._projection); - } - } - - const documents: IMongoDocument[] = []; - let count: number = 0; - while (count < this._batchSize) { - this._hasMoreChildren = await this._cursor.hasNext(); - if (this._hasMoreChildren) { - documents.push(await this._cursor.next()); - count += 1; - } else { - break; - } - } - this._batchSize *= 2; - - return this.createTreeItemsWithErrorHandling( - documents, - 'invalidMongoDocument', - doc => new MongoDocumentTreeItem(this, doc), - getDocumentTreeItemLabel - ); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - context.showCreatingTreeItem(""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result: InsertOneWriteOpResult = await this.collection.insertOne({}); - const newDocument: IMongoDocument = nonNullValue(await this.collection.findOne({ _id: result.insertedId }), 'newDocument'); - return new MongoDocumentTreeItem(this, newDocument); - } - - public async tryExecuteCommandDirectly(command: Partial): Promise<{ deferToShell: true; result: undefined } | { deferToShell: false; result: string }> { - // range and text are not neccessary properties for this function so partial should suffice - const parameters = command.arguments ? command.arguments.map(parseJSContent) : []; - - const functions = { - drop: new FunctionDescriptor(this.drop, 'Dropping collection', 0, 0, 0), - count: new FunctionDescriptor(this.count, 'Counting documents', 0, 2, 2), - findOne: new FunctionDescriptor(this.findOne, 'Finding document', 0, 2, 2), - insert: new FunctionDescriptor(this.insert, 'Inserting document', 1, 1, 1), - insertMany: new FunctionDescriptor(this.insertMany, 'Inserting documents', 1, 2, 2), - insertOne: new FunctionDescriptor(this.insertOne, 'Inserting document', 1, 2, 2), - deleteMany: new FunctionDescriptor(this.deleteMany, 'Deleting documents', 1, 2, 1), - deleteOne: new FunctionDescriptor(this.deleteOne, 'Deleting document', 1, 2, 1), - remove: new FunctionDescriptor(this.remove, 'Deleting document(s)', 1, 2, 1) - }; - - // eslint-disable-next-line no-prototype-builtins - if (command.name && functions.hasOwnProperty(command.name)) { - // currently no logic to handle chained commands so just defer to the shell right away - if (command.chained) { - return { deferToShell: true, result: undefined }; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const descriptor: FunctionDescriptor = functions[command.name]; - - if (parameters.length < descriptor.minShellArgs) { - throw new Error(`Too few arguments passed to command ${command.name}.`); - } - if (parameters.length > descriptor.maxShellArgs) { - throw new Error(`Too many arguments passed to command ${command.name}`); - } - if (parameters.length > descriptor.maxHandledArgs) { //this function won't handle these arguments, but the shell will - return { deferToShell: true, result: undefined }; - } - const result = await reportProgress(descriptor.mongoFunction.apply(this, parameters), descriptor.text); - return { deferToShell: false, result }; - } - return { deferToShell: true, result: undefined }; - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete collection '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoCollection' }, DialogResponses.deleteResponse); - await this.drop(); - } - - private async drop(): Promise { - try { - await this.collection.drop(); - return `Dropped collection '${this.collection.collectionName}'.`; - } catch (e) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const error: { code?: number, name?: string } = e; - const NamespaceNotFoundCode = 26; - if (error.name === 'MongoError' && error.code === NamespaceNotFoundCode) { - return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; - } else { - throw error; - } - } - } - - private async findOne(query?: Object, fieldsOption?: Object): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await this.collection.findOne(query || {}, { fields: fieldsOption }); - // findOne is the only command in this file whose output requires EJSON support. - // Hence that's the only function which uses EJSON.stringify rather than this.stringify. - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(result, null, '\t'); - } - - private async insert(document: Object): Promise { - if (!document) { - throw new Error("The insert command requires at least one argument"); - } - - const insertResult = await this.collection.insert(document); - return this.stringify(insertResult); - } - - private async insertOne(document: Object, options?: any): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const insertOneResult: InsertOneWriteOpResult = await this.collection.insertOne(document, { w: options && options.writeConcern }); - return this.stringify(insertOneResult); - } - - private async insertMany(documents: any[], options?: any): Promise { - assert.notEqual(documents.length, 0, "Array of documents cannot be empty"); - const insertManyOptions: CollectionInsertManyOptions = {}; - if (options) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.ordered) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.ordered = options.ordered; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (options.writeConcern) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - insertManyOptions.w = options.writeConcern; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const insertManyResult: InsertWriteOpResult = await this.collection.insertMany(documents, insertManyOptions); - return this.stringify(insertManyResult); - } - - private async remove(filter: Object): Promise { - const removeResult = await this.collection.remove(filter); - return this.stringify(removeResult); - } - - private async deleteOne(filter: Object): Promise { - const deleteOneResult: DeleteWriteOpResultObject = await this.collection.deleteOne(filter); - return this.stringify(deleteOneResult); - } - - private async deleteMany(filter: Object): Promise { - const deleteOpResult: DeleteWriteOpResultObject = await this.collection.deleteMany(filter); - return this.stringify(deleteOpResult); - } - - private async count(query?: Object[], options?: MongoCountPreferences): Promise { - const count = await this.collection.count(query, options); - return this.stringify(count); - } - - private stringify(result: any): string { - return JSON.stringify(result, null, '\t'); - } +export class MongoCollectionTreeItem + extends AzExtParentTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "MongoCollection"; + public readonly contextValue: string = MongoCollectionTreeItem.contextValue; + public readonly childTypeLabel: string = "Document"; + public readonly collection: Collection; + public parent: AzExtParentTreeItem; + public findArgs?: {}[]; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); + + private readonly _query: object | undefined; + private readonly _projection: object | undefined; + private _cursor: Cursor | undefined; + private _hasMoreChildren: boolean = true; + private _batchSize: number = getBatchSizeSetting(); + + constructor( + parent: AzExtParentTreeItem, + collection: Collection, + findArgs?: {}[] + ) { + super(parent); + this.collection = collection; + this.findArgs = findArgs; + if (findArgs && findArgs.length) { + this._query = findArgs[0]; + this._projection = findArgs.length > 1 ? findArgs[1] : undefined; + } + ext.fileSystem.fireChangedEvent(this); + } + + public async writeFileContent( + context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const documents: IMongoDocument[] = EJSON.parse(content); + const operations = documents.map((document) => { + return { + replaceOne: { + filter: { _id: document._id }, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + replacement: _.omit(document, "_id"), + upsert: false, + }, + }; + }); + + const result: BulkWriteOpResultObject = + await this.collection.bulkWrite(operations); + ext.outputChannel.appendLog( + `Successfully updated ${result.modifiedCount} document(s), inserted ${result.insertedCount} document(s)` + ); + + // The current tree item may have been a temporary one used to execute a scrapbook command. + // We want to refresh children for this one _and_ the actual one in the tree (if it's different) + const nodeInTree: MongoCollectionTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem(this.fullId, context); + const nodesToRefresh: MongoCollectionTreeItem[] = [this]; + if (nodeInTree && this !== nodeInTree) { + nodesToRefresh.push(nodeInTree); + } + + await Promise.all( + nodesToRefresh.map((n) => n.refreshChildren(context, documents)) + ); + + if (nodeInTree && this !== nodeInTree) { + // Don't need to fire a changed event on the item being saved at the moment. Just the node in the tree if it's different + ext.fileSystem.fireChangedEvent(nodeInTree); + } + } + + public async getFileContent(context: IActionContext): Promise { + const children = ( + await this.getCachedChildren(context) + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify( + children.map((c) => c.document), + null, + 2 + ); + } + + public get id(): string { + return this.collection.collectionName; + } + + public get label(): string { + return this.collection.collectionName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("files"); + } + + public get filePath(): string { + return this.label + "-cosmos-collection.json"; + } + + public async refreshImpl(): Promise { + this._batchSize = getBatchSizeSetting(); + ext.fileSystem.fireChangedEvent(this); + } + + public async refreshChildren( + context: IActionContext, + docs: IMongoDocument[] + ): Promise { + const documentNodes = ( + await this.getCachedChildren(context) + ); + for (const doc of docs) { + const documentNode = documentNodes.find( + (node) => node.document._id.toString() === doc._id.toString() + ); + if (documentNode) { + documentNode.document = doc; + await documentNode.refresh(context); + } + } + } + + public hasMoreChildrenImpl(): boolean { + return this._hasMoreChildren; + } + + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache || this._cursor === undefined) { + this._cursor = this.collection + .find(this._query) + .batchSize(this._batchSize); + if (this._projection) { + this._cursor = this._cursor.project(this._projection); + } + } + + const documents: IMongoDocument[] = []; + let count: number = 0; + while (count < this._batchSize) { + this._hasMoreChildren = await this._cursor.hasNext(); + if (this._hasMoreChildren) { + documents.push(await this._cursor.next()); + count += 1; + } else { + break; + } + } + this._batchSize *= 2; + + return this.createTreeItemsWithErrorHandling( + documents, + "invalidMongoDocument", + (doc) => new MongoDocumentTreeItem(this, doc), + getDocumentTreeItemLabel + ); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + context.showCreatingTreeItem(""); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result: InsertOneWriteOpResult = + await this.collection.insertOne({}); + const newDocument: IMongoDocument = nonNullValue( + await this.collection.findOne({ _id: result.insertedId }), + "newDocument" + ); + return new MongoDocumentTreeItem(this, newDocument); + } + + public async tryExecuteCommandDirectly( + command: Partial + ): Promise< + | { deferToShell: true; result: undefined } + | { deferToShell: false; result: string } + > { + // range and text are not neccessary properties for this function so partial should suffice + const parameters = command.arguments + ? command.arguments.map(parseJSContent) + : []; + + const functions = { + drop: new FunctionDescriptor( + this.drop, + "Dropping collection", + 0, + 0, + 0 + ), + count: new FunctionDescriptor( + this.count, + "Counting documents", + 0, + 2, + 2 + ), + findOne: new FunctionDescriptor( + this.findOne, + "Finding document", + 0, + 2, + 2 + ), + insert: new FunctionDescriptor( + this.insert, + "Inserting document", + 1, + 1, + 1 + ), + insertMany: new FunctionDescriptor( + this.insertMany, + "Inserting documents", + 1, + 2, + 2 + ), + insertOne: new FunctionDescriptor( + this.insertOne, + "Inserting document", + 1, + 2, + 2 + ), + deleteMany: new FunctionDescriptor( + this.deleteMany, + "Deleting documents", + 1, + 2, + 1 + ), + deleteOne: new FunctionDescriptor( + this.deleteOne, + "Deleting document", + 1, + 2, + 1 + ), + remove: new FunctionDescriptor( + this.remove, + "Deleting document(s)", + 1, + 2, + 1 + ), + }; + + // eslint-disable-next-line no-prototype-builtins + if (command.name && functions.hasOwnProperty(command.name)) { + // currently no logic to handle chained commands so just defer to the shell right away + if (command.chained) { + return { deferToShell: true, result: undefined }; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const descriptor: FunctionDescriptor = functions[command.name]; + + if (parameters.length < descriptor.minShellArgs) { + throw new Error( + `Too few arguments passed to command ${command.name}.` + ); + } + if (parameters.length > descriptor.maxShellArgs) { + throw new Error( + `Too many arguments passed to command ${command.name}` + ); + } + if (parameters.length > descriptor.maxHandledArgs) { + //this function won't handle these arguments, but the shell will + return { deferToShell: true, result: undefined }; + } + const result = await reportProgress( + descriptor.mongoFunction.apply(this, parameters), + descriptor.text + ); + return { deferToShell: false, result }; + } + return { deferToShell: true, result: undefined }; + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete collection '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoCollection" }, + DialogResponses.deleteResponse + ); + await this.drop(); + } + + private async drop(): Promise { + try { + await this.collection.drop(); + return `Dropped collection '${this.collection.collectionName}'.`; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const error: { code?: number; name?: string } = e; + const NamespaceNotFoundCode = 26; + if ( + error.name === "MongoError" && + error.code === NamespaceNotFoundCode + ) { + return `Collection '${this.collection.collectionName}' could not be dropped because it does not exist.`; + } else { + throw error; + } + } + } + + private async findOne( + query?: Object, + fieldsOption?: Object + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = await this.collection.findOne(query || {}, { + fields: fieldsOption, + }); + // findOne is the only command in this file whose output requires EJSON support. + // Hence that's the only function which uses EJSON.stringify rather than this.stringify. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(result, null, "\t"); + } + + private async insert(document: Object): Promise { + if (!document) { + throw new Error( + "The insert command requires at least one argument" + ); + } + + const insertResult = await this.collection.insert(document); + return this.stringify(insertResult); + } + + private async insertOne(document: Object, options?: any): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const insertOneResult: InsertOneWriteOpResult = + await this.collection.insertOne(document, { + w: options && options.writeConcern, + }); + return this.stringify(insertOneResult); + } + + private async insertMany(documents: any[], options?: any): Promise { + assert.notEqual( + documents.length, + 0, + "Array of documents cannot be empty" + ); + const insertManyOptions: CollectionInsertManyOptions = {}; + if (options) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.ordered) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.ordered = options.ordered; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (options.writeConcern) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + insertManyOptions.w = options.writeConcern; + } + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const insertManyResult: InsertWriteOpResult = + await this.collection.insertMany(documents, insertManyOptions); + return this.stringify(insertManyResult); + } + + private async remove(filter: Object): Promise { + const removeResult = await this.collection.remove(filter); + return this.stringify(removeResult); + } + + private async deleteOne(filter: Object): Promise { + const deleteOneResult: DeleteWriteOpResultObject = + await this.collection.deleteOne(filter); + return this.stringify(deleteOneResult); + } + + private async deleteMany(filter: Object): Promise { + const deleteOpResult: DeleteWriteOpResultObject = + await this.collection.deleteMany(filter); + return this.stringify(deleteOpResult); + } + + private async count( + query?: Object[], + options?: MongoCountPreferences + ): Promise { + const count = await this.collection.count(query, options); + return this.stringify(count); + } + + private stringify(result: any): string { + return JSON.stringify(result, null, "\t"); + } } function reportProgress(promise: Thenable, title: string): Thenable { - return vscode.window.withProgress( - { - location: vscode.ProgressLocation.Window, - title: title - }, - (_progress) => { - return promise; - }); + return vscode.window.withProgress( + { + location: vscode.ProgressLocation.Window, + title: title, + }, + (_progress) => { + return promise; + } + ); } function parseJSContent(content: string): any { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.parse(content); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - throw error.message; - } + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.parse(content); + } catch (error) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + throw error.message; + } } diff --git a/Source/mongo/tree/MongoDatabaseTreeItem.ts b/Source/mongo/tree/MongoDatabaseTreeItem.ts index 73a7c6a22..1fed13c80 100644 --- a/Source/mongo/tree/MongoDatabaseTreeItem.ts +++ b/Source/mongo/tree/MongoDatabaseTreeItem.ts @@ -3,256 +3,383 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, AzExtParentTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import { Collection, Db, DbCollectionOptions } from 'mongodb'; -import * as path from 'path'; -import * as process from 'process'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { connectToMongoClient } from '../connectToMongoClient'; -import { MongoCommand } from '../MongoCommand'; -import { addDatabaseToAccountConnectionString } from '../mongoConnectionStrings'; -import { MongoShell } from '../MongoShell'; -import { IMongoTreeRoot } from './IMongoTreeRoot'; -import { MongoAccountTreeItem } from './MongoAccountTreeItem'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongo'; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + DialogResponses, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, + UserCancelledError, +} from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import { Collection, Db, DbCollectionOptions } from "mongodb"; +import * as path from "path"; +import * as process from "process"; +import * as vscode from "vscode"; +import { ext } from "../../extensionVariables"; +import * as cpUtils from "../../utils/cp"; +import { nonNullProp, nonNullValue } from "../../utils/nonNull"; +import { connectToMongoClient } from "../connectToMongoClient"; +import { MongoCommand } from "../MongoCommand"; +import { addDatabaseToAccountConnectionString } from "../mongoConnectionStrings"; +import { MongoShell } from "../MongoShell"; +import { IMongoTreeRoot } from "./IMongoTreeRoot"; +import { MongoAccountTreeItem } from "./MongoAccountTreeItem"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; + +const mongoExecutableFileName = + process.platform === "win32" ? "mongo.exe" : "mongo"; const executingInShellMsg = "Executing command in Mongo shell"; export class MongoDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "mongoDb"; - public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Collection"; - public readonly connectionString: string; - public readonly databaseName: string; - public readonly parent: MongoAccountTreeItem; - - private _previousShellPathSetting: string | undefined; - private _cachedShellPathOrCmd: string | undefined; - - constructor(parent: MongoAccountTreeItem, databaseName: string, connectionString: string) { - super(parent); - this.databaseName = databaseName; - this.connectionString = addDatabaseToAccountConnectionString(connectionString, this.databaseName); - } - - public get root(): IMongoTreeRoot { - return this.parent.root; - } - - public get label(): string { - return this.databaseName; - } - - public get description(): string { - return ext.connectedMongoDB && ext.connectedMongoDB.fullId === this.fullId ? 'Connected' : ''; - } - - public get id(): string { - return this.databaseName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('database'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const db: Db = await this.connectToDb(); - const collections: Collection[] = await db.collections(); - return collections.map(collection => new MongoCollectionTreeItem(this, collection)); - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - const collectionName = await context.ui.showInputBox({ - placeHolder: "Collection Name", - prompt: "Enter the name of the collection", - stepName: 'createMongoCollection', - validateInput: validateMongoCollectionName - }); - - context.showCreatingTreeItem(collectionName); - return await this.createCollection(collectionName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete database '${this.label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDatabase' }, DialogResponses.deleteResponse); - const db = await this.connectToDb(); - await db.dropDatabase(); - } - - public async connectToDb(): Promise { - const accountConnection = await connectToMongoClient(this.connectionString, appendExtensionUserAgent()); - return accountConnection.db(this.databaseName); - } - - public async executeCommand(command: MongoCommand, context: IActionContext): Promise { - if (command.collection) { - const db = await this.connectToDb(); - const collection = db.collection(command.collection); - if (collection) { - const collectionTreeItem = new MongoCollectionTreeItem(this, collection, command.arguments); - const result = await collectionTreeItem.tryExecuteCommandDirectly(command); - if (!result.deferToShell) { - return result.result; - } - } - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - - } - - if (command.name === 'createCollection') { - // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead - return withProgress(this.createCollection(stripQuotes(nonNullProp(command, 'arguments')[0]), nonNullProp(command, 'argumentObjects')[1]).then(() => JSON.stringify({ Created: 'Ok' })), 'Creating collection'); - } else { - return withProgress(this.executeCommandInShell(command, context), executingInShellMsg); - } - } - - public async createCollection(collectionName: string, options?: DbCollectionOptions): Promise { - const db: Db = await this.connectToDb(); - const newCollection: Collection = await db.createCollection(collectionName, options); - // db.createCollection() doesn't create empty collections for some reason - // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection - const result = await newCollection.insertOne({}); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - await newCollection.deleteOne({ _id: result.insertedId }); - return new MongoCollectionTreeItem(this, newCollection); - } - - private async executeCommandInShell(command: MongoCommand, context: IActionContext): Promise { - context.telemetry.properties.executeInShell = "true"; - - if (this.root.isEmulator) { - // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info - await this.connectToDb(); - } - - // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state - // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out - // requests. - const shell = await this.createShell(context); - try { - await shell.useDatabase(this.databaseName); - return await shell.executeScript(command.text); - } finally { - shell.dispose(); - } - } - - private async createShell(context: IActionContext): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.mongoShellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.mongoShellArgs, []); - - if (!shellPath || !this._cachedShellPathOrCmd || this._previousShellPathSetting !== shellPath) { - // Only do this if setting changed since last time - shellPath = await this._determineShellPathOrCmd(context, shellPath); - this._previousShellPathSetting = shellPath; - } - this._cachedShellPathOrCmd = shellPath; - - const timeout = 1000 * nonNullValue(config.get(ext.settingsKeys.mongoShellTimeout), 'mongoShellTimeout'); - return MongoShell.create(shellPath, shellArgs, this.connectionString, this.root.isEmulator, ext.outputChannel, timeout); - } - - private async _determineShellPathOrCmd(context: IActionContext, shellPathSetting: string | undefined): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongo', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongo'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { title: `Browse to ${mongoExecutableFileName}` }; - const browse: vscode.MessageItem = { title: 'Open installation page' }; - const noMongoError: string = 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting.'; - const response = await context.ui.showWarningMessage(noMongoError, { stepName: 'promptForMongoPath' }, browse, openFile); - if (response === openFile) { - // eslint-disable-next-line no-constant-condition - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: `Select ${mongoExecutableFileName}`, - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: 'Use anyway' }; - const tryAgain: vscode.MessageItem = { title: 'Try again' }; - const response2 = await context.ui.showWarningMessage( - `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace.getConfiguration().update(ext.settingsKeys.mongoShellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://docs.mongodb.com/manual/installation/')); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await fse.pathExists(shellPathSetting)) { - const stat = await fse.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } + public static contextValue: string = "mongoDb"; + public readonly contextValue: string = MongoDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Collection"; + public readonly connectionString: string; + public readonly databaseName: string; + public readonly parent: MongoAccountTreeItem; + + private _previousShellPathSetting: string | undefined; + private _cachedShellPathOrCmd: string | undefined; + + constructor( + parent: MongoAccountTreeItem, + databaseName: string, + connectionString: string + ) { + super(parent); + this.databaseName = databaseName; + this.connectionString = addDatabaseToAccountConnectionString( + connectionString, + this.databaseName + ); + } + + public get root(): IMongoTreeRoot { + return this.parent.root; + } + + public get label(): string { + return this.databaseName; + } + + public get description(): string { + return ext.connectedMongoDB && + ext.connectedMongoDB.fullId === this.fullId + ? "Connected" + : ""; + } + + public get id(): string { + return this.databaseName; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("database"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const db: Db = await this.connectToDb(); + const collections: Collection[] = await db.collections(); + return collections.map( + (collection) => new MongoCollectionTreeItem(this, collection) + ); + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + const collectionName = await context.ui.showInputBox({ + placeHolder: "Collection Name", + prompt: "Enter the name of the collection", + stepName: "createMongoCollection", + validateInput: validateMongoCollectionName, + }); + + context.showCreatingTreeItem(collectionName); + return await this.createCollection(collectionName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete database '${this.label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoDatabase" }, + DialogResponses.deleteResponse + ); + const db = await this.connectToDb(); + await db.dropDatabase(); + } + + public async connectToDb(): Promise { + const accountConnection = await connectToMongoClient( + this.connectionString, + appendExtensionUserAgent() + ); + return accountConnection.db(this.databaseName); + } + + public async executeCommand( + command: MongoCommand, + context: IActionContext + ): Promise { + if (command.collection) { + const db = await this.connectToDb(); + const collection = db.collection(command.collection); + if (collection) { + const collectionTreeItem = new MongoCollectionTreeItem( + this, + collection, + command.arguments + ); + const result = + await collectionTreeItem.tryExecuteCommandDirectly(command); + if (!result.deferToShell) { + return result.result; + } + } + return withProgress( + this.executeCommandInShell(command, context), + executingInShellMsg + ); + } + + if (command.name === "createCollection") { + // arguments are all strings so DbCollectionOptions is represented as a JSON string which is why we pass argumentObjects instead + return withProgress( + this.createCollection( + stripQuotes(nonNullProp(command, "arguments")[0]), + nonNullProp(command, "argumentObjects")[1] + ).then(() => JSON.stringify({ Created: "Ok" })), + "Creating collection" + ); + } else { + return withProgress( + this.executeCommandInShell(command, context), + executingInShellMsg + ); + } + } + + public async createCollection( + collectionName: string, + options?: DbCollectionOptions + ): Promise { + const db: Db = await this.connectToDb(); + const newCollection: Collection = await db.createCollection( + collectionName, + options + ); + // db.createCollection() doesn't create empty collections for some reason + // However, we can 'insert' and then 'delete' a document, which has the side-effect of creating an empty collection + const result = await newCollection.insertOne({}); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + await newCollection.deleteOne({ _id: result.insertedId }); + return new MongoCollectionTreeItem(this, newCollection); + } + + private async executeCommandInShell( + command: MongoCommand, + context: IActionContext + ): Promise { + context.telemetry.properties.executeInShell = "true"; + + if (this.root.isEmulator) { + // Ensure the emulator is running before creating the shell. Shell errors are generic and don't include emulator specific info + await this.connectToDb(); + } + + // CONSIDER: Re-using the shell instead of disposing it each time would allow us to keep state + // (JavaScript variables, etc.), but we would need to deal with concurrent requests, or timed-out + // requests. + const shell = await this.createShell(context); + try { + await shell.useDatabase(this.databaseName); + return await shell.executeScript(command.text); + } finally { + shell.dispose(); + } + } + + private async createShell(context: IActionContext): Promise { + const config = vscode.workspace.getConfiguration(); + let shellPath: string | undefined = config.get( + ext.settingsKeys.mongoShellPath + ); + const shellArgs: string[] = config.get( + ext.settingsKeys.mongoShellArgs, + [] + ); + + if ( + !shellPath || + !this._cachedShellPathOrCmd || + this._previousShellPathSetting !== shellPath + ) { + // Only do this if setting changed since last time + shellPath = await this._determineShellPathOrCmd(context, shellPath); + this._previousShellPathSetting = shellPath; + } + this._cachedShellPathOrCmd = shellPath; + + const timeout = + 1000 * + nonNullValue( + config.get(ext.settingsKeys.mongoShellTimeout), + "mongoShellTimeout" + ); + return MongoShell.create( + shellPath, + shellArgs, + this.connectionString, + this.root.isEmulator, + ext.outputChannel, + timeout + ); + } + + private async _determineShellPathOrCmd( + context: IActionContext, + shellPathSetting: string | undefined + ): Promise { + if (!shellPathSetting) { + // User hasn't specified the path + if (await cpUtils.commandSucceeds("mongo", "--version")) { + // If the user already has mongo in their system path, just use that + return "mongo"; + } else { + // If all else fails, prompt the user for the mongo path + const openFile: vscode.MessageItem = { + title: `Browse to ${mongoExecutableFileName}`, + }; + const browse: vscode.MessageItem = { + title: "Open installation page", + }; + const noMongoError: string = + "This functionality requires the Mongo DB shell, but we could not find it in the path or using the mongo.shell.path setting."; + const response = await context.ui.showWarningMessage( + noMongoError, + { stepName: "promptForMongoPath" }, + browse, + openFile + ); + if (response === openFile) { + // eslint-disable-next-line no-constant-condition + while (true) { + const newPath: vscode.Uri[] = + await context.ui.showOpenDialog({ + filters: { + "Executable Files": [ + process.platform === "win32" + ? "exe" + : "", + ], + }, + openLabel: `Select ${mongoExecutableFileName}`, + stepName: "openMongoExeFile", + }); + const fsPath = newPath[0].fsPath; + const baseName = path.basename(fsPath); + if (baseName !== mongoExecutableFileName) { + const useAnyway: vscode.MessageItem = { + title: "Use anyway", + }; + const tryAgain: vscode.MessageItem = { + title: "Try again", + }; + const response2 = + await context.ui.showWarningMessage( + `Expected a file named "${mongoExecutableFileName}, but the selected filename is "${baseName}"`, + { stepName: "confirmMongoExeFile" }, + useAnyway, + tryAgain + ); + if (response2 === tryAgain) { + continue; + } + } + + await vscode.workspace + .getConfiguration() + .update( + ext.settingsKeys.mongoShellPath, + fsPath, + vscode.ConfigurationTarget.Global + ); + return fsPath; + } + } else if (response === browse) { + void vscode.commands.executeCommand( + "vscode.open", + vscode.Uri.parse( + "https://docs.mongodb.com/manual/installation/" + ) + ); + // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath + } + + throw new UserCancelledError("createShell"); + } + } else { + // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix + if (await fse.pathExists(shellPathSetting)) { + const stat = await fse.stat(shellPathSetting); + if (stat.isDirectory()) { + return path.join(shellPathSetting, mongoExecutableFileName); + } + } + + return shellPathSetting; + } + } } -export function validateMongoCollectionName(collectionName: string): string | undefined | null { - // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names - if (!collectionName) { - return "Collection name cannot be empty"; - } - const systemPrefix = "system."; - if (collectionName.startsWith(systemPrefix)) { - return `"${systemPrefix}" prefix is reserved for internal use`; - } - if (/[$]/.test(collectionName)) { - return "Collection name cannot contain $"; - } - return undefined; +export function validateMongoCollectionName( + collectionName: string +): string | undefined | null { + // https://docs.mongodb.com/manual/reference/limits/#Restriction-on-Collection-Names + if (!collectionName) { + return "Collection name cannot be empty"; + } + const systemPrefix = "system."; + if (collectionName.startsWith(systemPrefix)) { + return `"${systemPrefix}" prefix is reserved for internal use`; + } + if (/[$]/.test(collectionName)) { + return "Collection name cannot contain $"; + } + return undefined; } -function withProgress(promise: Thenable, title: string, location: vscode.ProgressLocation = vscode.ProgressLocation.Window): Thenable { - return vscode.window.withProgress( - { - location: location, - title: title - }, - (_progress) => { - return promise; - }); +function withProgress( + promise: Thenable, + title: string, + location: vscode.ProgressLocation = vscode.ProgressLocation.Window +): Thenable { + return vscode.window.withProgress( + { + location: location, + title: title, + }, + (_progress) => { + return promise; + } + ); } export function stripQuotes(term: string): string { - if ((term.startsWith('\'') && term.endsWith('\'')) - || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; + if ( + (term.startsWith("'") && term.endsWith("'")) || + (term.startsWith('"') && term.endsWith('"')) + ) { + return term.substring(1, term.length - 1); + } + return term; } diff --git a/Source/mongo/tree/MongoDocumentTreeItem.ts b/Source/mongo/tree/MongoDocumentTreeItem.ts index ad44e43c3..dae87ed84 100644 --- a/Source/mongo/tree/MongoDocumentTreeItem.ts +++ b/Source/mongo/tree/MongoDocumentTreeItem.ts @@ -3,95 +3,131 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { Collection, DeleteWriteOpResultObject, ObjectID, UpdateWriteOpResult } from 'mongodb'; -import * as _ from 'underscore'; -import * as vscode from 'vscode'; -import { IEditableTreeItem } from '../../DatabasesFileSystem'; -import { ext } from '../../extensionVariables'; -import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils'; -import { MongoCollectionTreeItem } from './MongoCollectionTreeItem'; +import { + AzExtTreeItem, + DialogResponses, + IActionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { + Collection, + DeleteWriteOpResultObject, + ObjectID, + UpdateWriteOpResult, +} from "mongodb"; +import * as _ from "underscore"; +import * as vscode from "vscode"; +import { IEditableTreeItem } from "../../DatabasesFileSystem"; +import { ext } from "../../extensionVariables"; +import { getDocumentTreeItemLabel } from "../../utils/vscodeUtils"; +import { MongoCollectionTreeItem } from "./MongoCollectionTreeItem"; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const EJSON = require("mongodb-extended-json"); export interface IMongoDocument { - _id: string | ObjectID; + _id: string | ObjectID; - // custom properties - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + // custom properties + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [key: string]: any; } -export class MongoDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem { - public static contextValue: string = "MongoDocument"; - public readonly contextValue: string = MongoDocumentTreeItem.contextValue; - public document: IMongoDocument; - public readonly parent: MongoCollectionTreeItem; - public readonly cTime: number = Date.now(); - public mTime: number = Date.now(); +export class MongoDocumentTreeItem + extends AzExtTreeItem + implements IEditableTreeItem +{ + public static contextValue: string = "MongoDocument"; + public readonly contextValue: string = MongoDocumentTreeItem.contextValue; + public document: IMongoDocument; + public readonly parent: MongoCollectionTreeItem; + public readonly cTime: number = Date.now(); + public mTime: number = Date.now(); - private _label: string; + private _label: string; - constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { - super(parent); - this.document = document; - this._label = getDocumentTreeItemLabel(this.document); - this.commandId = 'cosmosDB.openDocument'; - ext.fileSystem.fireChangedEvent(this); - } + constructor(parent: MongoCollectionTreeItem, document: IMongoDocument) { + super(parent); + this.document = document; + this._label = getDocumentTreeItemLabel(this.document); + this.commandId = "cosmosDB.openDocument"; + ext.fileSystem.fireChangedEvent(this); + } - public get id(): string { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return String(this.document!._id); - } + public get id(): string { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return String(this.document!._id); + } - public get label(): string { - return this._label; - } + public get label(): string { + return this._label; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('file'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("file"); + } - public get filePath(): string { - return this.label + '-cosmos-document.json'; - } + public get filePath(): string { + return this.label + "-cosmos-document.json"; + } - public static async update(collection: Collection, newDocument: IMongoDocument): Promise { - if (!newDocument._id) { - throw new Error(`The "_id" field is required to update a document.`); - } - const filter: object = { _id: newDocument._id }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const result: UpdateWriteOpResult = await collection.replaceOne(filter, _.omit(newDocument, '_id')); - if (result.modifiedCount !== 1) { - throw new Error(`Failed to update document with _id '${newDocument._id}'.`); - } - return newDocument; - } + public static async update( + collection: Collection, + newDocument: IMongoDocument + ): Promise { + if (!newDocument._id) { + throw new Error( + `The "_id" field is required to update a document.` + ); + } + const filter: object = { _id: newDocument._id }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const result: UpdateWriteOpResult = await collection.replaceOne( + filter, + _.omit(newDocument, "_id") + ); + if (result.modifiedCount !== 1) { + throw new Error( + `Failed to update document with _id '${newDocument._id}'.` + ); + } + return newDocument; + } - public async getFileContent(): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return EJSON.stringify(this.document, null, 2); - } + public async getFileContent(): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return EJSON.stringify(this.document, null, 2); + } - public async refreshImpl(): Promise { - this._label = getDocumentTreeItemLabel(this.document); - ext.fileSystem.fireChangedEvent(this); - } + public async refreshImpl(): Promise { + this._label = getDocumentTreeItemLabel(this.document); + ext.fileSystem.fireChangedEvent(this); + } - public async deleteTreeItemImpl(context: IActionContext): Promise { - const message: string = `Are you sure you want to delete document '${this._label}'?`; - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteMongoDocument' }, DialogResponses.deleteResponse); - const deleteResult: DeleteWriteOpResultObject = await this.parent.collection.deleteOne({ _id: this.document._id }); - if (deleteResult.deletedCount !== 1) { - throw new Error(`Failed to delete document with _id '${this.document._id}'.`); - } - } + public async deleteTreeItemImpl(context: IActionContext): Promise { + const message: string = `Are you sure you want to delete document '${this._label}'?`; + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deleteMongoDocument" }, + DialogResponses.deleteResponse + ); + const deleteResult: DeleteWriteOpResultObject = + await this.parent.collection.deleteOne({ _id: this.document._id }); + if (deleteResult.deletedCount !== 1) { + throw new Error( + `Failed to delete document with _id '${this.document._id}'.` + ); + } + } - public async writeFileContent(_context: IActionContext, content: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const newDocument: IMongoDocument = EJSON.parse(content); - this.document = await MongoDocumentTreeItem.update(this.parent.collection, newDocument); - } + public async writeFileContent( + _context: IActionContext, + content: string + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const newDocument: IMongoDocument = EJSON.parse(content); + this.document = await MongoDocumentTreeItem.update( + this.parent.collection, + newDocument + ); + } } diff --git a/Source/postgres/abstract/AbstractPostgresClient.ts b/Source/postgres/abstract/AbstractPostgresClient.ts index c1fa29c4f..ca6bd3d9a 100644 --- a/Source/postgres/abstract/AbstractPostgresClient.ts +++ b/Source/postgres/abstract/AbstractPostgresClient.ts @@ -6,18 +6,26 @@ import { PostgreSQLManagementClient as PostgreSQLSingleManagementClient } from "@azure/arm-postgresql"; import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; import { AzExtClientContext } from "@microsoft/vscode-azext-azureutils"; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../utils/azureClients"; +import { + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../../utils/azureClients"; import { PostgresServerType } from "./models"; -export type AbstractPostgresClient = PostgreSQLFlexibleManagementClient | PostgreSQLSingleManagementClient; +export type AbstractPostgresClient = + | PostgreSQLFlexibleManagementClient + | PostgreSQLSingleManagementClient; -export async function createAbstractPostgresClient(serverType: PostgresServerType, context: AzExtClientContext): Promise { - switch (serverType) { - case PostgresServerType.Flexible: - return await createPostgreSQLFlexibleClient(context) - case PostgresServerType.Single: - return await createPostgreSQLClient(context) - default: - throw new Error("Service not implemented."); - } +export async function createAbstractPostgresClient( + serverType: PostgresServerType, + context: AzExtClientContext +): Promise { + switch (serverType) { + case PostgresServerType.Flexible: + return await createPostgreSQLFlexibleClient(context); + case PostgresServerType.Single: + return await createPostgreSQLClient(context); + default: + throw new Error("Service not implemented."); + } } diff --git a/Source/postgres/abstract/models.ts b/Source/postgres/abstract/models.ts index 6bdadf16a..046185de1 100644 --- a/Source/postgres/abstract/models.ts +++ b/Source/postgres/abstract/models.ts @@ -7,49 +7,58 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; export enum PostgresServerType { - Flexible = 'Flexible', - Single = 'Single' + Flexible = "Flexible", + Single = "Single", } -export type PostgresAbstractServer = (SingleModels.Server | FlexibleModels.Server) & { serverType?: PostgresServerType; } +export type PostgresAbstractServer = ( + | SingleModels.Server + | FlexibleModels.Server +) & { serverType?: PostgresServerType }; -export type PostgresAbstractDatabase = SingleModels.Database | FlexibleModels.Database; +export type PostgresAbstractDatabase = + | SingleModels.Database + | FlexibleModels.Database; /** * Billing information related properties of a server. */ export interface AbstractSku { - /** - * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - */ - name: string; - /** - * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', - * 'GeneralPurpose', 'MemoryOptimized' - */ - tier: SingleModels.SkuTier | FlexibleModels.SkuTier; - /** - * The scale up/out capacity, representing server's compute units. - */ - capacity?: number; - /** - * The size code, to be interpreted by resource as appropriate. - */ - size?: string; - /** - * The family of hardware. - */ - family?: string; + /** + * The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + */ + name: string; + /** + * The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', + * 'GeneralPurpose', 'MemoryOptimized' + */ + tier: SingleModels.SkuTier | FlexibleModels.SkuTier; + /** + * The scale up/out capacity, representing server's compute units. + */ + capacity?: number; + /** + * The size code, to be interpreted by resource as appropriate. + */ + size?: string; + /** + * The family of hardware. + */ + family?: string; } export interface AbstractServerCreate { - location: string; - sku: AbstractSku; - administratorLogin: string; - administratorLoginPassword: string; - size: number; + location: string; + sku: AbstractSku; + administratorLogin: string; + administratorLoginPassword: string; + size: number; } -export type AbstractNameAvailability = SingleModels.NameAvailability | FlexibleModels.NameAvailability; +export type AbstractNameAvailability = + | SingleModels.NameAvailability + | FlexibleModels.NameAvailability; -export type AbstractFirewallRule = SingleModels.FirewallRule | FlexibleModels.FirewallRule; +export type AbstractFirewallRule = + | SingleModels.FirewallRule + | FlexibleModels.FirewallRule; diff --git a/Source/postgres/commands/checkAuthentication.ts b/Source/postgres/commands/checkAuthentication.ts index 6799d060c..c26bc25be 100644 --- a/Source/postgres/commands/checkAuthentication.ts +++ b/Source/postgres/commands/checkAuthentication.ts @@ -3,7 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IParsedError, parseError } from "@microsoft/vscode-azext-utils"; +import { + IActionContext, + IParsedError, + parseError, +} from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; import { invalidCredentialsErrorType } from "../postgresConstants"; import { PostgresClientConfigFactory } from "../tree/ClientConfigFactory"; @@ -11,26 +15,34 @@ import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; import { configurePostgresFirewall } from "./configurePostgresFirewall"; import { enterPostgresCredentials } from "./enterPostgresCredentials"; -export async function checkAuthentication(context: IActionContext, treeItem: PostgresDatabaseTreeItem): Promise { - let clientConfig: ClientConfig | undefined; - while (!clientConfig) { - const isFirewallRuleSet = await treeItem.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - await configurePostgresFirewall(context, treeItem.parent); - continue; - } - try { - const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName); - clientConfig = getClientConfigResult.clientConfig; - } catch (error) { - const parsedError: IParsedError = parseError(error); +export async function checkAuthentication( + context: IActionContext, + treeItem: PostgresDatabaseTreeItem +): Promise { + let clientConfig: ClientConfig | undefined; + while (!clientConfig) { + const isFirewallRuleSet = + await treeItem.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + await configurePostgresFirewall(context, treeItem.parent); + continue; + } + try { + const getClientConfigResult = + await PostgresClientConfigFactory.getClientConfigFromNode( + treeItem.parent, + treeItem.databaseName + ); + clientConfig = getClientConfigResult.clientConfig; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - await enterPostgresCredentials(context, treeItem.parent); - } else { - throw error; - } - } - } - return clientConfig; + if (parsedError.errorType === invalidCredentialsErrorType) { + await enterPostgresCredentials(context, treeItem.parent); + } else { + throw error; + } + } + } + return clientConfig; } diff --git a/Source/postgres/commands/configurePostgresFirewall.ts b/Source/postgres/commands/configurePostgresFirewall.ts index 52a378fca..86779ff9b 100644 --- a/Source/postgres/commands/configurePostgresFirewall.ts +++ b/Source/postgres/commands/configurePostgresFirewall.ts @@ -4,66 +4,102 @@ *--------------------------------------------------------------------------------------------*/ import { DialogResponses, IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { getPublicIpv4 } from "../../utils/getIp"; import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { AbstractFirewallRule, PostgresServerType } from '../abstract/models'; +import { nonNullProp } from "../../utils/nonNull"; +import { randomUtils } from "../../utils/randomUtils"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../abstract/AbstractPostgresClient"; +import { AbstractFirewallRule, PostgresServerType } from "../abstract/models"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function configurePostgresFirewall(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function configurePostgresFirewall( + context: IActionContext, + treeItem?: PostgresServerTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - const ip: string = await getPublicIp(context); - await context.ui.showWarningMessage( - localize('firewallRuleWillBeAdded', 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', ip, treeItem.label), - { - modal: true, - stepName: 'postgresAddFirewallRule' - }, - { title: DialogResponses.yes.title } - ); + const ip: string = await getPublicIp(context); + await context.ui.showWarningMessage( + localize( + "firewallRuleWillBeAdded", + 'A firewall rule for your IP ({0}) will be added to server "{1}". Would you like to continue?', + ip, + treeItem.label + ), + { + modal: true, + stepName: "postgresAddFirewallRule", + }, + { title: DialogResponses.yes.title } + ); - await setFirewallRule(context, treeItem, ip); + await setFirewallRule(context, treeItem, ip); } -export async function setFirewallRule(context: IActionContext, treeItem: PostgresServerTreeItem, ip: string): Promise { +export async function setFirewallRule( + context: IActionContext, + treeItem: PostgresServerTreeItem, + ip: string +): Promise { + const serverType: PostgresServerType = nonNullProp(treeItem, "serverType"); + const client: AbstractPostgresClient = await createAbstractPostgresClient( + serverType, + [context, treeItem.subscription] + ); + const resourceGroup: string = nonNullProp(treeItem, "resourceGroup"); + const serverName: string = nonNullProp(treeItem, "azureName"); - const serverType: PostgresServerType = nonNullProp(treeItem, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, treeItem.subscription]); - const resourceGroup: string = nonNullProp(treeItem, 'resourceGroup'); - const serverName: string = nonNullProp(treeItem, 'azureName'); + const firewallRuleName: string = + "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; - const firewallRuleName: string = "azDbVSCode-Ip" + `-${randomUtils.getRandomHexString(6)}`; + const newFirewallRule: AbstractFirewallRule = { + startIpAddress: ip, + endIpAddress: ip, + }; - const newFirewallRule: AbstractFirewallRule = { - startIpAddress: ip, - endIpAddress: ip - }; - - const progressMessage: string = localize('configuringFirewallRule', 'Adding firewall rule for IP "{0}" to server "{1}"...', ip, serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; - ext.outputChannel.appendLog(progressMessage); - await vscode.window.withProgress(options, async () => { - await client.firewallRules.beginCreateOrUpdateAndWait(resourceGroup, serverName, firewallRuleName, newFirewallRule); - }); - const completedMessage: string = localize('addedFirewallRule', 'Successfully added firewall rule for IP "{0}" to server "{1}".', ip, serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - await treeItem.refresh(context); + const progressMessage: string = localize( + "configuringFirewallRule", + 'Adding firewall rule for IP "{0}" to server "{1}"...', + ip, + serverName + ); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage, + }; + ext.outputChannel.appendLog(progressMessage); + await vscode.window.withProgress(options, async () => { + await client.firewallRules.beginCreateOrUpdateAndWait( + resourceGroup, + serverName, + firewallRuleName, + newFirewallRule + ); + }); + const completedMessage: string = localize( + "addedFirewallRule", + 'Successfully added firewall rule for IP "{0}" to server "{1}".', + ip, + serverName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + await treeItem.refresh(context); } export async function getPublicIp(context: IActionContext): Promise { - return await getPublicIpv4(context); + return await getPublicIpv4(context); } diff --git a/Source/postgres/commands/connectPostgresDatabase.ts b/Source/postgres/commands/connectPostgresDatabase.ts index 6996f7d03..9437c8c70 100644 --- a/Source/postgres/commands/connectPostgresDatabase.ts +++ b/Source/postgres/commands/connectPostgresDatabase.ts @@ -4,36 +4,52 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { Uri, window } from 'vscode'; -import { connectedPostgresKey, postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; +import { Uri, window } from "vscode"; +import { + connectedPostgresKey, + postgresFlexibleFilter, + postgresSingleFilter, +} from "../../constants"; import { ext } from "../../extensionVariables"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function connectPostgresDatabase(context: IActionContext, treeItem?: Uri | PostgresDatabaseTreeItem): Promise { - if (!treeItem || treeItem instanceof Uri) { - if (treeItem) { - void window.showTextDocument(treeItem); - } - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } +export async function connectPostgresDatabase( + context: IActionContext, + treeItem?: Uri | PostgresDatabaseTreeItem +): Promise { + if (!treeItem || treeItem instanceof Uri) { + if (treeItem) { + void window.showTextDocument(treeItem); + } + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - const oldTreeItemId: string | undefined = ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; - void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); - ext.connectedPostgresDB = treeItem; - const database = treeItem && treeItem.label; - if (ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(database); - } - await treeItem.refresh(context); + const oldTreeItemId: string | undefined = + ext.connectedPostgresDB && ext.connectedPostgresDB.fullId; + void ext.context.globalState.update(connectedPostgresKey, treeItem.fullId); + ext.connectedPostgresDB = treeItem; + const database = treeItem && treeItem.label; + if (ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase(database); + } + await treeItem.refresh(context); - if (oldTreeItemId) { - // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date - const oldTreeItem: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(oldTreeItemId, context); - if (oldTreeItem) { - await oldTreeItem.refresh(context); - } - } + if (oldTreeItemId) { + // We have to use findTreeItem to get the instance of the old tree item that's being displayed in the ext.rgApi.appResourceTree. Our specific instance might have been out-of-date + const oldTreeItem: AzExtTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + oldTreeItemId, + context + ); + if (oldTreeItem) { + await oldTreeItem.refresh(context); + } + } } diff --git a/Source/postgres/commands/copyConnectionString.ts b/Source/postgres/commands/copyConnectionString.ts index 716bbd5b6..6d9bcbcf2 100644 --- a/Source/postgres/commands/copyConnectionString.ts +++ b/Source/postgres/commands/copyConnectionString.ts @@ -3,34 +3,56 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { addDatabaseToConnectionString, copyPostgresConnectionString } from '../postgresConnectionStrings'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { + addDatabaseToConnectionString, + copyPostgresConnectionString, +} from "../postgresConnectionStrings"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { checkAuthentication } from "./checkAuthentication"; -export async function copyConnectionString(context: IActionContext, node: PostgresDatabaseTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } +export async function copyConnectionString( + context: IActionContext, + node: PostgresDatabaseTreeItem +): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - await checkAuthentication(context, node); - const parsedConnectionString = await node.parent.getFullConnectionString(); - let connectionString: string; - if (node.parent.azureName) { - const parsedCS = await node.parent.getFullConnectionString(); - connectionString = copyPostgresConnectionString(parsedCS.hostName, parsedCS.port, parsedCS.username, parsedCS.password, node.databaseName); - } else { - connectionString = addDatabaseToConnectionString(parsedConnectionString.connectionString, node.databaseName); - } + await checkAuthentication(context, node); + const parsedConnectionString = await node.parent.getFullConnectionString(); + let connectionString: string; + if (node.parent.azureName) { + const parsedCS = await node.parent.getFullConnectionString(); + connectionString = copyPostgresConnectionString( + parsedCS.hostName, + parsedCS.port, + parsedCS.username, + parsedCS.password, + node.databaseName + ); + } else { + connectionString = addDatabaseToConnectionString( + parsedConnectionString.connectionString, + node.databaseName + ); + } - await vscode.env.clipboard.writeText(connectionString); - const message = localize('copiedPostgresConnectStringMsg', 'The connection string has been copied to the clipboard'); - void vscode.window.showInformationMessage(message); + await vscode.env.clipboard.writeText(connectionString); + const message = localize( + "copiedPostgresConnectStringMsg", + "The connection string has been copied to the clipboard" + ); + void vscode.window.showInformationMessage(message); } diff --git a/Source/postgres/commands/createPostgresDatabase.ts b/Source/postgres/commands/createPostgresDatabase.ts index 6c096a52b..c86e5ac45 100644 --- a/Source/postgres/commands/createPostgresDatabase.ts +++ b/Source/postgres/commands/createPostgresDatabase.ts @@ -3,24 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; -import { connectPostgresDatabase } from './connectPostgresDatabase'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; +import { connectPostgresDatabase } from "./connectPostgresDatabase"; -export async function createPostgresDatabase(context: IActionContext, node?: PostgresServerTreeItem): Promise { - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } - const newDatabase: PostgresDatabaseTreeItem = await node.createChild(context); - await connectPostgresDatabase(context, newDatabase); - const createMessage: string = localize('createPostgresDatabaseMsg', 'Successfully created database "{0}".', newDatabase.databaseName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); +export async function createPostgresDatabase( + context: IActionContext, + node?: PostgresServerTreeItem +): Promise { + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } + const newDatabase: PostgresDatabaseTreeItem = + await node.createChild(context); + await connectPostgresDatabase(context, newDatabase); + const createMessage: string = localize( + "createPostgresDatabaseMsg", + 'Successfully created database "{0}".', + newDatabase.databaseName + ); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); } diff --git a/Source/postgres/commands/deletePostgresDatabase.ts b/Source/postgres/commands/deletePostgresDatabase.ts index a09520bde..705b8823f 100644 --- a/Source/postgres/commands/deletePostgresDatabase.ts +++ b/Source/postgres/commands/deletePostgresDatabase.ts @@ -3,28 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; -export async function deletePostgresDatabase(context: IActionContext, node?: PostgresDatabaseTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresDatabase', 'Are you sure you want to delete database "{0}"?', node.databaseName); - const result = await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresDatabase' }, DialogResponses.deleteResponse); - if (result === DialogResponses.deleteResponse) { - await node.deleteTreeItem(context); - } - const deleteMessage: string = localize('deletePostgresDatabaseMsg', 'Successfully deleted database "{0}".', node.databaseName); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresDatabase( + context: IActionContext, + node?: PostgresDatabaseTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } + const message: string = localize( + "deletesPostgresDatabase", + 'Are you sure you want to delete database "{0}"?', + node.databaseName + ); + const result = await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresDatabase" }, + DialogResponses.deleteResponse + ); + if (result === DialogResponses.deleteResponse) { + await node.deleteTreeItem(context); + } + const deleteMessage: string = localize( + "deletePostgresDatabaseMsg", + 'Successfully deleted database "{0}".', + node.databaseName + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresFunction.ts b/Source/postgres/commands/deletePostgresFunction.ts index 9a4547428..9ee7a21d7 100644 --- a/Source/postgres/commands/deletePostgresFunction.ts +++ b/Source/postgres/commands/deletePostgresFunction.ts @@ -3,27 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function deletePostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } +export async function deletePostgresFunction( + context: IActionContext, + treeItem?: PostgresFunctionTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresFunctionTreeItem.contextValue, + } + ); + } - const message: string = localize('deleteFunction', 'Are you sure you want to delete function "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresFunction' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedFunction', 'Successfully deleted function "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize( + "deleteFunction", + 'Are you sure you want to delete function "{0}"?', + treeItem.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresFunction" }, + DialogResponses.deleteResponse + ); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedFunction", + 'Successfully deleted function "{0}".', + treeItem.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresServer.ts b/Source/postgres/commands/deletePostgresServer.ts index 733c6fca6..686b3c134 100644 --- a/Source/postgres/commands/deletePostgresServer.ts +++ b/Source/postgres/commands/deletePostgresServer.ts @@ -3,20 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, ITreeItemPickerContext } from '@microsoft/vscode-azext-utils'; -import { deleteDatabaseAccount } from '../../commands/deleteDatabaseAccount/deleteDatabaseAccount'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { PostgresServerTreeItem } from '../tree/PostgresServerTreeItem'; +import { + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { deleteDatabaseAccount } from "../../commands/deleteDatabaseAccount/deleteDatabaseAccount"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; -export async function deletePostgresServer(context: IActionContext, node?: PostgresServerTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function deletePostgresServer( + context: IActionContext, + node?: PostgresServerTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - await deleteDatabaseAccount(context, node, true) + await deleteDatabaseAccount(context, node, true); } diff --git a/Source/postgres/commands/deletePostgresStoredProcedure.ts b/Source/postgres/commands/deletePostgresStoredProcedure.ts index 6abece79b..244a207d2 100644 --- a/Source/postgres/commands/deletePostgresStoredProcedure.ts +++ b/Source/postgres/commands/deletePostgresStoredProcedure.ts @@ -3,27 +3,51 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { PostgresStoredProcedureTreeItem } from '../tree/PostgresStoredProcedureTreeItem'; +import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function deletePostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } +export async function deletePostgresStoredProcedure( + context: IActionContext, + treeItem?: PostgresStoredProcedureTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!treeItem) { + treeItem = + await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresStoredProcedureTreeItem.contextValue, + } + ); + } - const message: string = localize('deleteStoredProcedure', 'Are you sure you want to delete stored procedure "{0}"?', treeItem.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresStoredProcedure' }, DialogResponses.deleteResponse); - await treeItem.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedStoredProcedure', 'Successfully deleted stored procedure "{0}".', treeItem.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); + const message: string = localize( + "deleteStoredProcedure", + 'Are you sure you want to delete stored procedure "{0}"?', + treeItem.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresStoredProcedure" }, + DialogResponses.deleteResponse + ); + await treeItem.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedStoredProcedure", + 'Successfully deleted stored procedure "{0}".', + treeItem.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/deletePostgresTable.ts b/Source/postgres/commands/deletePostgresTable.ts index bfdce33a2..60cfb0c18 100644 --- a/Source/postgres/commands/deletePostgresTable.ts +++ b/Source/postgres/commands/deletePostgresTable.ts @@ -3,26 +3,48 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DialogResponses, IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils"; -import { window } from 'vscode'; +import { + DialogResponses, + IActionContext, + ITreeItemPickerContext, +} from "@microsoft/vscode-azext-utils"; +import { window } from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; import { PostgresTableTreeItem } from "../tree/PostgresTableTreeItem"; -export async function deletePostgresTable(context: IActionContext, node?: PostgresTableTreeItem): Promise { - const suppressCreateContext: ITreeItemPickerContext = context; - suppressCreateContext.suppressCreatePick = true; - if (!node) { - node = await ext.rgApi.pickAppResource({ ...context, suppressCreatePick: true }, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresTableTreeItem.contextValue - }); - } - const message: string = localize('deletesPostgresTable', 'Are you sure you want to delete table "{0}"?', node.label); - await context.ui.showWarningMessage(message, { modal: true, stepName: 'deletePostgresTable' }, DialogResponses.deleteResponse); - await node.deleteTreeItem(context); - const deleteMessage: string = localize('successfullyDeletedTable', 'Successfully deleted table "{0}".', node.label); - void window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); +export async function deletePostgresTable( + context: IActionContext, + node?: PostgresTableTreeItem +): Promise { + const suppressCreateContext: ITreeItemPickerContext = context; + suppressCreateContext.suppressCreatePick = true; + if (!node) { + node = await ext.rgApi.pickAppResource( + { ...context, suppressCreatePick: true }, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: PostgresTableTreeItem.contextValue, + } + ); + } + const message: string = localize( + "deletesPostgresTable", + 'Are you sure you want to delete table "{0}"?', + node.label + ); + await context.ui.showWarningMessage( + message, + { modal: true, stepName: "deletePostgresTable" }, + DialogResponses.deleteResponse + ); + await node.deleteTreeItem(context); + const deleteMessage: string = localize( + "successfullyDeletedTable", + 'Successfully deleted table "{0}".', + node.label + ); + void window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); } diff --git a/Source/postgres/commands/enterPostgresCredentials.ts b/Source/postgres/commands/enterPostgresCredentials.ts index aa993c337..ff146d290 100644 --- a/Source/postgres/commands/enterPostgresCredentials.ts +++ b/Source/postgres/commands/enterPostgresCredentials.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as vscode from 'vscode'; +import * as vscode from "vscode"; import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { nonNullProp } from '../../utils/nonNull'; -import { PostgresServerType } from '../abstract/models'; +import { nonNullProp } from "../../utils/nonNull"; +import { PostgresServerType } from "../abstract/models"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; import { setPostgresCredentials } from "./setPostgresCredentials"; @@ -17,69 +17,118 @@ import { setPostgresCredentials } from "./setPostgresCredentials"; * Get the username and password for the Postgres database from user input. */ async function getUsernamePassword( - context: IActionContext, - serverType: PostgresServerType, - serverName: string, - serverDisplayName: string -): Promise<{ username: string, password: string }> { - let username: string = await context.ui.showInputBox({ - prompt: localize('enterUsername', 'Enter username for server "{0}"', serverDisplayName), - stepName: 'enterPostgresUsername', - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('usernameCannotBeEmpty', 'Username cannot be empty.'); } - }); + context: IActionContext, + serverType: PostgresServerType, + serverName: string, + serverDisplayName: string +): Promise<{ username: string; password: string }> { + let username: string = await context.ui.showInputBox({ + prompt: localize( + "enterUsername", + 'Enter username for server "{0}"', + serverDisplayName + ), + stepName: "enterPostgresUsername", + validateInput: (value: string) => { + return value && value.length + ? undefined + : localize( + "usernameCannotBeEmpty", + "Username cannot be empty." + ); + }, + }); - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexible Server instance - const usernameSuffix: string = `@${serverName}`; - if (serverType === PostgresServerType.Single && !username.includes(usernameSuffix)) { - username += usernameSuffix; - } + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexible Server instance + const usernameSuffix: string = `@${serverName}`; + if ( + serverType === PostgresServerType.Single && + !username.includes(usernameSuffix) + ) { + username += usernameSuffix; + } - const password: string = await context.ui.showInputBox({ - prompt: localize('enterPassword', 'Enter password for server "{0}"', serverDisplayName), - stepName: 'enterPostgresPassword', - password: true, - validateInput: (value: string) => { return (value && value.length) ? undefined : localize('passwordCannotBeEmpty', 'Password cannot be empty.'); } - }); + const password: string = await context.ui.showInputBox({ + prompt: localize( + "enterPassword", + 'Enter password for server "{0}"', + serverDisplayName + ), + stepName: "enterPostgresPassword", + password: true, + validateInput: (value: string) => { + return value && value.length + ? undefined + : localize( + "passwordCannotBeEmpty", + "Password cannot be empty." + ); + }, + }); - return { username, password }; + return { username, password }; } /** * Save the username and password in secure local storage. */ -async function persistUsernamePassword(id: string, serverName: string, username: string, password: string): Promise { - const progressMessage: string = localize('setupCredentialsMessage', 'Setting up credentials for server "{0}"...', serverName); - const options: vscode.ProgressOptions = { - location: vscode.ProgressLocation.Notification, - title: progressMessage - }; +async function persistUsernamePassword( + id: string, + serverName: string, + username: string, + password: string +): Promise { + const progressMessage: string = localize( + "setupCredentialsMessage", + 'Setting up credentials for server "{0}"...', + serverName + ); + const options: vscode.ProgressOptions = { + location: vscode.ProgressLocation.Notification, + title: progressMessage, + }; - await vscode.window.withProgress(options, async () => { - await setPostgresCredentials(username, password, id); - }); + await vscode.window.withProgress(options, async () => { + await setPostgresCredentials(username, password, id); + }); - const completedMessage: string = localize('setupCredentialsMessage', 'Successfully added credentials to server "{0}".', serverName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); + const completedMessage: string = localize( + "setupCredentialsMessage", + 'Successfully added credentials to server "{0}".', + serverName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); } -export async function enterPostgresCredentials(context: IActionContext, treeItem?: PostgresServerTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter] - }); - } +export async function enterPostgresCredentials( + context: IActionContext, + treeItem?: PostgresServerTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + } + ); + } - const serverType = treeItem.serverType; - const serverName: string = nonNullProp(treeItem, 'azureName'); - const serverDisplayName: string = treeItem.label; - const id: string = nonNullProp(treeItem, 'id'); + const serverType = treeItem.serverType; + const serverName: string = nonNullProp(treeItem, "azureName"); + const serverDisplayName: string = treeItem.label; + const id: string = nonNullProp(treeItem, "id"); - const { username, password } = await getUsernamePassword(context, serverType, serverName, serverDisplayName); + const { username, password } = await getUsernamePassword( + context, + serverType, + serverName, + serverDisplayName + ); - await persistUsernamePassword(id, serverName, username, password); + await persistUsernamePassword(id, serverName, username, password); - treeItem.setCredentials(username, password); - await treeItem.refresh(context); + treeItem.setCredentials(username, password); + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/executePostgresQueryInDocument.ts b/Source/postgres/commands/executePostgresQueryInDocument.ts index af5d3ca5e..4aedb847b 100644 --- a/Source/postgres/commands/executePostgresQueryInDocument.ts +++ b/Source/postgres/commands/executePostgresQueryInDocument.ts @@ -3,63 +3,92 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { EOL } from 'os'; -import * as path from 'path'; -import { ClientConfig, QueryResult } from 'pg'; -import * as vscode from 'vscode'; -import { postgresFlexibleFilter, postgresSingleFilter } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import * as vscodeUtil from '../../utils/vscodeUtils'; -import { runPostgresQuery } from '../runPostgresQuery'; -import { PostgresDatabaseTreeItem } from '../tree/PostgresDatabaseTreeItem'; -import { checkAuthentication } from './checkAuthentication'; -import { loadPersistedPostgresDatabase } from './registerPostgresCommands'; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { EOL } from "os"; +import * as path from "path"; +import { ClientConfig, QueryResult } from "pg"; +import * as vscode from "vscode"; +import { postgresFlexibleFilter, postgresSingleFilter } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import * as vscodeUtil from "../../utils/vscodeUtils"; +import { runPostgresQuery } from "../runPostgresQuery"; +import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem"; +import { checkAuthentication } from "./checkAuthentication"; +import { loadPersistedPostgresDatabase } from "./registerPostgresCommands"; -export async function executePostgresQueryInDocument(context: IActionContext): Promise { - await loadPersistedPostgresDatabase(); +export async function executePostgresQueryInDocument( + context: IActionContext +): Promise { + await loadPersistedPostgresDatabase(); - let treeItem: PostgresDatabaseTreeItem; - if (ext.connectedPostgresDB) { - treeItem = ext.connectedPostgresDB; - } else { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresDatabaseTreeItem.contextValue - }); - } + let treeItem: PostgresDatabaseTreeItem; + if (ext.connectedPostgresDB) { + treeItem = ext.connectedPostgresDB; + } else { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresDatabaseTreeItem.contextValue, + } + ); + } - const clientConfig: ClientConfig = await checkAuthentication(context, treeItem); + const clientConfig: ClientConfig = await checkAuthentication( + context, + treeItem + ); - const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + const activeEditor: vscode.TextEditor | undefined = + vscode.window.activeTextEditor; - if (!activeEditor?.document) { - throw new Error(localize('openQueryBeforeExecuting', 'Open a PostgreSQL query before executing.')); - } + if (!activeEditor?.document) { + throw new Error( + localize( + "openQueryBeforeExecuting", + "Open a PostgreSQL query before executing." + ) + ); + } - const query: string | undefined = activeEditor.document.getText(); - const queryResult: QueryResult = await runPostgresQuery(clientConfig, query); - ext.outputChannel.appendLine(localize('executedQuery', 'Successfully executed "{0}" query.', queryResult.command)); + const query: string | undefined = activeEditor.document.getText(); + const queryResult: QueryResult = await runPostgresQuery( + clientConfig, + query + ); + ext.outputChannel.appendLine( + localize( + "executedQuery", + 'Successfully executed "{0}" query.', + queryResult.command + ) + ); - if (queryResult.rowCount) { - const fileExtension: string = path.extname(activeEditor.document.fileName); - const queryFileName: string = path.basename(activeEditor.document.fileName, fileExtension); - const outputFileName: string = `${queryFileName}-output`; + if (queryResult.rowCount) { + const fileExtension: string = path.extname( + activeEditor.document.fileName + ); + const queryFileName: string = path.basename( + activeEditor.document.fileName, + fileExtension + ); + const outputFileName: string = `${queryFileName}-output`; - const fields: string[] = queryResult.fields.map(f => f.name); - let csvData: string = `${fields.join(',')}${EOL}`; + const fields: string[] = queryResult.fields.map((f) => f.name); + let csvData: string = `${fields.join(",")}${EOL}`; - for (const row of queryResult.rows) { - const fieldValues: string[] = []; - for (const field of fields) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - fieldValues.push(row[field]); - } - csvData += `${fieldValues.join(',')}${EOL}`; - } + for (const row of queryResult.rows) { + const fieldValues: string[] = []; + for (const field of fields) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + fieldValues.push(row[field]); + } + csvData += `${fieldValues.join(",")}${EOL}`; + } - await vscodeUtil.showNewFile(csvData, outputFileName, '.csv'); - } - await treeItem.refresh(context); + await vscodeUtil.showNewFile(csvData, outputFileName, ".csv"); + } + await treeItem.refresh(context); } diff --git a/Source/postgres/commands/openPostgresFunction.ts b/Source/postgres/commands/openPostgresFunction.ts index 26103970f..4b186ed71 100644 --- a/Source/postgres/commands/openPostgresFunction.ts +++ b/Source/postgres/commands/openPostgresFunction.ts @@ -9,13 +9,20 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresFunctionTreeItem } from "../tree/PostgresFunctionTreeItem"; -export async function openPostgresFunction(context: IActionContext, treeItem?: PostgresFunctionTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresFunctionTreeItem.contextValue - }); - } +export async function openPostgresFunction( + context: IActionContext, + treeItem?: PostgresFunctionTreeItem +): Promise { + if (!treeItem) { + treeItem = await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresFunctionTreeItem.contextValue, + } + ); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/openPostgresStoredProcedure.ts b/Source/postgres/commands/openPostgresStoredProcedure.ts index 3c98ff743..1eb8931aa 100644 --- a/Source/postgres/commands/openPostgresStoredProcedure.ts +++ b/Source/postgres/commands/openPostgresStoredProcedure.ts @@ -9,13 +9,21 @@ import { ext } from "../../extensionVariables"; import { showPostgresQuery } from "../showPostgresQuery"; import { PostgresStoredProcedureTreeItem } from "../tree/PostgresStoredProcedureTreeItem"; -export async function openPostgresStoredProcedure(context: IActionContext, treeItem?: PostgresStoredProcedureTreeItem): Promise { - if (!treeItem) { - treeItem = await ext.rgApi.pickAppResource(context, { - filter: [postgresSingleFilter, postgresFlexibleFilter], - expectedChildContextValue: PostgresStoredProcedureTreeItem.contextValue - }); - } +export async function openPostgresStoredProcedure( + context: IActionContext, + treeItem?: PostgresStoredProcedureTreeItem +): Promise { + if (!treeItem) { + treeItem = + await ext.rgApi.pickAppResource( + context, + { + filter: [postgresSingleFilter, postgresFlexibleFilter], + expectedChildContextValue: + PostgresStoredProcedureTreeItem.contextValue, + } + ); + } - await showPostgresQuery(treeItem); + await showPostgresQuery(treeItem); } diff --git a/Source/postgres/commands/registerPostgresCommands.ts b/Source/postgres/commands/registerPostgresCommands.ts index b861e00f7..89412a2ba 100644 --- a/Source/postgres/commands/registerPostgresCommands.ts +++ b/Source/postgres/commands/registerPostgresCommands.ts @@ -3,10 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, + registerCommandWithTreeNodeUnwrapping, +} from "@microsoft/vscode-azext-utils"; import { defaults } from "pg"; import { languages } from "vscode"; -import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants"; +import { + connectedPostgresKey, + doubleClickDebounceDelay, + postgresDefaultDatabase, + postgresLanguageId, +} from "../../constants"; import { ext } from "../../extensionVariables"; import { openUrl } from "../../utils/openUrl"; import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider"; @@ -28,55 +37,126 @@ import { openPostgresFunction } from "./openPostgresFunction"; import { openPostgresStoredProcedure } from "./openPostgresStoredProcedure"; export function registerPostgresCommands(): void { - ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); - ext.context.subscriptions.push(languages.registerCodeLensProvider(postgresLanguageId, ext.postgresCodeLensProvider)); + ext.postgresCodeLensProvider = new PostgresCodeLensProvider(); + ext.context.subscriptions.push( + languages.registerCodeLensProvider( + postgresLanguageId, + ext.postgresCodeLensProvider + ) + ); - void loadPersistedPostgresDatabase(); + void loadPersistedPostgresDatabase(); - //update defaults.database of 'pg' - defaults.database = postgresDefaultDatabase; + //update defaults.database of 'pg' + defaults.database = postgresDefaultDatabase; - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteServer', deletePostgresServer); - registerCommandWithTreeNodeUnwrapping('postgreSQL.enterCredentials', enterPostgresCredentials); - registerCommandWithTreeNodeUnwrapping('postgreSQL.configureFirewall', configurePostgresFirewall); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createDatabase', createPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteDatabase', deletePostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteTable', deletePostgresTable); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openFunction', openPostgresFunction, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.openStoredProcedure', openPostgresStoredProcedure, doubleClickDebounceDelay); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteFunction', deletePostgresFunction); - registerCommandWithTreeNodeUnwrapping('postgreSQL.deleteStoredProcedure', deletePostgresStoredProcedure); - registerCommandWithTreeNodeUnwrapping('postgreSQL.connectDatabase', connectPostgresDatabase); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createFunctionQuery', createPostgresFunctionQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery); - registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument); - registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString); - registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteServer", + deletePostgresServer + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.enterCredentials", + enterPostgresCredentials + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.configureFirewall", + configurePostgresFirewall + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createDatabase", + createPostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteDatabase", + deletePostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteTable", + deletePostgresTable + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.openFunction", + openPostgresFunction, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.openStoredProcedure", + openPostgresStoredProcedure, + doubleClickDebounceDelay + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteFunction", + deletePostgresFunction + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.deleteStoredProcedure", + deletePostgresStoredProcedure + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.connectDatabase", + connectPostgresDatabase + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createFunctionQuery", + createPostgresFunctionQuery + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.createStoredProcedureQuery", + createPostgresStoredProcedureQuery + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.executeQuery", + executePostgresQueryInDocument + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.copyConnectionString", + copyConnectionString + ); + registerCommandWithTreeNodeUnwrapping( + "postgreSQL.showPasswordlessWiki", + showPasswordlessWiki + ); } export async function loadPersistedPostgresDatabase(): Promise { - // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times - await callWithTelemetryAndErrorHandling('postgreSQL.loadPersistedDatabase', async (context: IActionContext) => { - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.isActivationEvent = 'true'; + // NOTE: We want to make sure this function never throws or returns a rejected promise because it gets awaited multiple times + await callWithTelemetryAndErrorHandling( + "postgreSQL.loadPersistedDatabase", + async (context: IActionContext) => { + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.isActivationEvent = "true"; - try { - const persistedTreeItemId: string | undefined = ext.context.globalState.get(connectedPostgresKey); - if (persistedTreeItemId) { - const persistedTreeItem: PostgresDatabaseTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(persistedTreeItemId, context); - if (persistedTreeItem) { - await connectPostgresDatabase(context, persistedTreeItem); - } - } - } finally { - // Get code lens provider out of initializing state if there's no connected DB - if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { - ext.postgresCodeLensProvider.setConnectedDatabase(undefined); - } - } - }); + try { + const persistedTreeItemId: string | undefined = + ext.context.globalState.get(connectedPostgresKey); + if (persistedTreeItemId) { + const persistedTreeItem: + | PostgresDatabaseTreeItem + | undefined = ( + await ext.rgApi.appResourceTree.findTreeItem( + persistedTreeItemId, + context + ) + ); + if (persistedTreeItem) { + await connectPostgresDatabase( + context, + persistedTreeItem + ); + } + } + } finally { + // Get code lens provider out of initializing state if there's no connected DB + if (!ext.connectedPostgresDB && ext.postgresCodeLensProvider) { + ext.postgresCodeLensProvider.setConnectedDatabase( + undefined + ); + } + } + } + ); } export async function showPasswordlessWiki(): Promise { - await openUrl("https://aka.ms/postgresql-passwordless-wiki"); + await openUrl("https://aka.ms/postgresql-passwordless-wiki"); } diff --git a/Source/postgres/commands/setPostgresCredentials.ts b/Source/postgres/commands/setPostgresCredentials.ts index 8df8260f6..2807acc3c 100644 --- a/Source/postgres/commands/setPostgresCredentials.ts +++ b/Source/postgres/commands/setPostgresCredentials.ts @@ -8,25 +8,37 @@ import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; import { PostgresServerTreeItem } from "../tree/PostgresServerTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } -export async function setPostgresCredentials(username: string, password: string, serverId: string): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; +export async function setPostgresCredentials( + username: string, + password: string, + serverId: string +): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = + ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue + ? JSON.parse(storedValue) + : []; - // Remove this server from the cache if it's there - servers = servers.filter((server: IPersistedServer) => { return server.id !== serverId; }); + // Remove this server from the cache if it's there + servers = servers.filter((server: IPersistedServer) => { + return server.id !== serverId; + }); - const newServer: IPersistedServer = { - id: serverId, - username - }; + const newServer: IPersistedServer = { + id: serverId, + username, + }; - servers.push(newServer); - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.store(getSecretStorageKey(serviceName, serverId), password); + servers.push(newServer); + await ext.context.globalState.update(serviceName, JSON.stringify(servers)); + await ext.secretStorage.store( + getSecretStorageKey(serviceName, serverId), + password + ); } diff --git a/Source/postgres/getClientConfig.ts b/Source/postgres/getClientConfig.ts index bdc545945..431a95bea 100644 --- a/Source/postgres/getClientConfig.ts +++ b/Source/postgres/getClientConfig.ts @@ -8,12 +8,15 @@ import { ConnectionOptions } from "tls"; import { postgresDefaultPort } from "../constants"; import { nonNullProp } from "../utils/nonNull"; import { PostgresServerType } from "./abstract/models"; -import { ParsedPostgresConnectionString, addDatabaseToConnectionString } from "./postgresConnectionStrings"; +import { + ParsedPostgresConnectionString, + addDatabaseToConnectionString, +} from "./postgresConnectionStrings"; export type PostgresClientConfigs = { - password: ClientConfig | undefined; - azureAd: ClientConfig | undefined; - connectionString: ClientConfig | undefined; + password: ClientConfig | undefined; + azureAd: ClientConfig | undefined; + connectionString: ClientConfig | undefined; }; export type PostgresClientConfigType = keyof PostgresClientConfigs; @@ -21,82 +24,133 @@ export type PostgresClientConfigType = keyof PostgresClientConfigs; * Test if the database can be connected to using the given client config. * @throws if the client failed to connect to the database. */ -export async function testClientConfig(clientConfig: ClientConfig): Promise { - const client = new Client(clientConfig); - try { - await client.connect(); - } finally { - await client.end(); - } +export async function testClientConfig( + clientConfig: ClientConfig +): Promise { + const client = new Client(clientConfig); + try { + await client.connect(); + } finally { + await client.end(); + } } -async function getConnectionStringClientConfig(parsedConnectionString: ParsedPostgresConnectionString, databaseName: string): Promise { - let connectionString = parsedConnectionString.connectionString; - if (!parsedConnectionString.databaseName) { - connectionString = addDatabaseToConnectionString(connectionString, databaseName); - } - return { connectionString: connectionString }; +async function getConnectionStringClientConfig( + parsedConnectionString: ParsedPostgresConnectionString, + databaseName: string +): Promise { + let connectionString = parsedConnectionString.connectionString; + if (!parsedConnectionString.databaseName) { + connectionString = addDatabaseToConnectionString( + connectionString, + databaseName + ); + } + return { connectionString: connectionString }; } -async function getUsernamePasswordClientConfig(parsedConnectionString: ParsedPostgresConnectionString, sslAzure: ConnectionOptions, databaseName: string): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - const username: string | undefined = parsedConnectionString.username; - const password: string | undefined = parsedConnectionString.password; +async function getUsernamePasswordClientConfig( + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string +): Promise { + const host = nonNullProp(parsedConnectionString, "hostName"); + const port: number = parsedConnectionString.port + ? parseInt(parsedConnectionString.port) + : parseInt(postgresDefaultPort); + const username: string | undefined = parsedConnectionString.username; + const password: string | undefined = parsedConnectionString.password; - if (!!username && !!password && !!host && !!port) { - return { user: username, password, ssl: sslAzure, host, port, database: databaseName }; - } else { - return undefined; - } + if (!!username && !!password && !!host && !!port) { + return { + user: username, + password, + ssl: sslAzure, + host, + port, + database: databaseName, + }; + } else { + return undefined; + } } async function getAzureAdClientConfig( - parsedConnectionString: ParsedPostgresConnectionString, - sslAzure: ConnectionOptions, - databaseName: string, - azureAdUserId: string, - getToken: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + sslAzure: ConnectionOptions, + databaseName: string, + azureAdUserId: string, + getToken: () => Promise ): Promise { - const host = nonNullProp(parsedConnectionString, 'hostName'); - const port: number = parsedConnectionString.port ? parseInt(parsedConnectionString.port) : parseInt(postgresDefaultPort); - return { user: azureAdUserId, password: getToken, ssl: sslAzure, host, port, database: databaseName }; + const host = nonNullProp(parsedConnectionString, "hostName"); + const port: number = parsedConnectionString.port + ? parseInt(parsedConnectionString.port) + : parseInt(postgresDefaultPort); + return { + user: azureAdUserId, + password: getToken, + ssl: sslAzure, + host, + port, + database: databaseName, + }; } export async function getClientConfigs( - parsedConnectionString: ParsedPostgresConnectionString, - serverType: PostgresServerType, - hasSubscription: boolean, - databaseName: string, - azureUserId?: string, - getToken?: () => Promise + parsedConnectionString: ParsedPostgresConnectionString, + serverType: PostgresServerType, + hasSubscription: boolean, + databaseName: string, + azureUserId?: string, + getToken?: () => Promise ): Promise { - const clientConfigs: PostgresClientConfigs = { - password: undefined, - azureAd: undefined, - connectionString: undefined - }; - if (hasSubscription) { - const sslAzure: ConnectionOptions = { - // Always provide the certificate since it is accepted even when SSL is disabled - // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) - // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 - ca: serverType === PostgresServerType.Single ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] : [DigiCertGlobalRootCA] - }; - const passwordClientConfig = await getUsernamePasswordClientConfig(parsedConnectionString, sslAzure, databaseName); - if (passwordClientConfig) { - clientConfigs.password = passwordClientConfig; - } - if (serverType === PostgresServerType.Flexible && !!azureUserId && !!getToken) { - const azureAdClientConfig = await getAzureAdClientConfig(parsedConnectionString, sslAzure, databaseName, azureUserId, getToken); - clientConfigs.azureAd = azureAdClientConfig; - } - } else { - const connectionStringClientConfig = await getConnectionStringClientConfig(parsedConnectionString, databaseName); - clientConfigs.connectionString = connectionStringClientConfig; - } + const clientConfigs: PostgresClientConfigs = { + password: undefined, + azureAd: undefined, + connectionString: undefined, + }; + if (hasSubscription) { + const sslAzure: ConnectionOptions = { + // Always provide the certificate since it is accepted even when SSL is disabled + // Single Server Root Cert --> BaltimoreCyberTrustRoot (Current), DigiCertGlobalRootG2 (TBA) + // Flexible Server Root Cert --> DigiCertGlobalRootCA. More info: https://aka.ms/AAd75x5 + ca: + serverType === PostgresServerType.Single + ? [BaltimoreCyberTrustRoot, DigiCertGlobalRootG2] + : [DigiCertGlobalRootCA], + }; + const passwordClientConfig = await getUsernamePasswordClientConfig( + parsedConnectionString, + sslAzure, + databaseName + ); + if (passwordClientConfig) { + clientConfigs.password = passwordClientConfig; + } + if ( + serverType === PostgresServerType.Flexible && + !!azureUserId && + !!getToken + ) { + const azureAdClientConfig = await getAzureAdClientConfig( + parsedConnectionString, + sslAzure, + databaseName, + azureUserId, + getToken + ); + clientConfigs.azureAd = azureAdClientConfig; + } + } else { + const connectionStringClientConfig = + await getConnectionStringClientConfig( + parsedConnectionString, + databaseName + ); + clientConfigs.connectionString = connectionStringClientConfig; + } - return clientConfigs; + return clientConfigs; } // Postgres Single Server Root Cert, https://aka.ms/AA7wnvl @@ -169,4 +223,3 @@ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE-----`; - diff --git a/Source/postgres/getPostgresProcedureQueryRows.ts b/Source/postgres/getPostgresProcedureQueryRows.ts index ad791ff2e..0cecca979 100644 --- a/Source/postgres/getPostgresProcedureQueryRows.ts +++ b/Source/postgres/getPostgresProcedureQueryRows.ts @@ -9,16 +9,16 @@ import { PostgresFunctionsTreeItem } from "./tree/PostgresFunctionsTreeItem"; import { PostgresResourcesTreeItemBase } from "./tree/PostgresResourcesTreeItemBase"; export interface IPostgresProceduresQueryRow { - schema: string; - name: string; - oid: number; - args: string; - definition: string; + schema: string; + name: string; + oid: number; + args: string; + definition: string; } function getProceduresQuery(conditions: string): string { - // Adapted from https://aka.ms/AA83fg8 - return `select n.nspname as schema, + // Adapted from https://aka.ms/AA83fg8 + return `select n.nspname as schema, p.proname as name, p.oid as oid, pg_get_function_arguments(p.oid) as args, @@ -33,26 +33,37 @@ function getProceduresQuery(conditions: string): string { order by name;`; } -export async function getPostgresProcedureQueryRows(treeItem: PostgresResourcesTreeItemBase): Promise { - let conditions: string; +export async function getPostgresProcedureQueryRows( + treeItem: PostgresResourcesTreeItemBase +): Promise { + let conditions: string; - if (treeItem instanceof PostgresFunctionsTreeItem) { - conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') - ${await treeItem.parent.parent.supportsStoredProcedures(treeItem.clientConfig) ? "and p.prokind = 'f'" : ''}`; - } else { - // Assume stored procedures - conditions = "and p.prokind = 'p'"; - } + if (treeItem instanceof PostgresFunctionsTreeItem) { + conditions = `and p.proname not in ('pg_buffercache_pages', 'pg_stat_statements_reset', 'pg_stat_statements') + ${ + (await treeItem.parent.parent.supportsStoredProcedures( + treeItem.clientConfig + )) + ? "and p.prokind = 'f'" + : "" + }`; + } else { + // Assume stored procedures + conditions = "and p.prokind = 'p'"; + } - const query: string = getProceduresQuery(conditions); - const queryResult: QueryResult = await runPostgresQuery(treeItem.clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; + const query: string = getProceduresQuery(conditions); + const queryResult: QueryResult = await runPostgresQuery( + treeItem.clientConfig, + query + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const rows: IPostgresProceduresQueryRow[] = queryResult.rows || []; - treeItem.resourcesAndSchemas = {}; - for (const row of rows) { - treeItem.addResourcesAndSchemasEntry(row.name, row.schema); - } + treeItem.resourcesAndSchemas = {}; + for (const row of rows) { + treeItem.addResourcesAndSchemasEntry(row.name, row.schema); + } - return rows; + return rows; } diff --git a/Source/postgres/getTables.ts b/Source/postgres/getTables.ts index ebc7d1c75..e74d1074d 100644 --- a/Source/postgres/getTables.ts +++ b/Source/postgres/getTables.ts @@ -7,10 +7,10 @@ import { ClientConfig, QueryResult } from "pg"; import { runPostgresQuery } from "./runPostgresQuery"; export interface IPostgresTable { - schemaName: string; - name: string; - oid: string; - columnNames: string[]; + schemaName: string; + name: string; + oid: string; + columnNames: string[]; } const tablesQuery: string = `select schemaname, tablename, array_agg (columnname) as columnnames, @@ -23,12 +23,22 @@ const tablesQuery: string = `select schemaname, tablename, array_agg (columnname where schemaname != 'pg_catalog' AND schemaname != 'information_schema' group by schemaname, tablename;`; -export async function getTables(clientConfig: ClientConfig): Promise { - const tableInfoRows: QueryResult = await runPostgresQuery(clientConfig, tablesQuery); - const tablesArray: IPostgresTable[] = []; - for (const row of tableInfoRows.rows) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - tablesArray.push({ schemaName: row.schemaname, name: row.tablename, oid: row.oid, columnNames: row.columnnames }); - } - return tablesArray; +export async function getTables( + clientConfig: ClientConfig +): Promise { + const tableInfoRows: QueryResult = await runPostgresQuery( + clientConfig, + tablesQuery + ); + const tablesArray: IPostgresTable[] = []; + for (const row of tableInfoRows.rows) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + tablesArray.push({ + schemaName: row.schemaname, + name: row.tablename, + oid: row.oid, + columnNames: row.columnnames, + }); + } + return tablesArray; } diff --git a/Source/postgres/postgresConnectionStrings.ts b/Source/postgres/postgresConnectionStrings.ts index ea9ce9e2e..f1c46e6e7 100644 --- a/Source/postgres/postgresConnectionStrings.ts +++ b/Source/postgres/postgresConnectionStrings.ts @@ -8,67 +8,84 @@ import { postgresDefaultPort } from "../constants"; import { ParsedConnectionString } from "../ParsedConnectionString"; import { nonNullProp } from "../utils/nonNull"; -export function parsePostgresConnectionString(connectionString: string): ParsedPostgresConnectionString { - const config: ConnectionOptions = parse(connectionString.trim()); - return new ParsedPostgresConnectionString(connectionString, config); +export function parsePostgresConnectionString( + connectionString: string +): ParsedPostgresConnectionString { + const config: ConnectionOptions = parse(connectionString.trim()); + return new ParsedPostgresConnectionString(connectionString, config); } -export function addDatabaseToConnectionString(connectionString: string, databaseName: string): string { - const url = new URL(connectionString); - url.pathname = encodeURIComponent(databaseName); - return url.toString(); +export function addDatabaseToConnectionString( + connectionString: string, + databaseName: string +): string { + const url = new URL(connectionString); + url.pathname = encodeURIComponent(databaseName); + return url.toString(); } -export function createPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - connectionString += `${encodedUsername}:${encodedPassword}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function createPostgresConnectionString( + hostName: string, + port: string = postgresDefaultPort, + username?: string | undefined, + password?: string | undefined, + databaseName?: string | undefined +): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + connectionString += `${encodedUsername}:${encodedPassword}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } -export function copyPostgresConnectionString(hostName: string, port: string = postgresDefaultPort, username?: string | undefined, password?: string | undefined, databaseName?: string | undefined): string { - let connectionString: string = `postgres://`; - if (username) { - const encodedUsername = encodeURIComponent(username); - if (password) { - const encodedPassword = encodeURIComponent(password); - const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; - connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; - } else { - connectionString += `${encodedUsername}@`; - } - } - connectionString += `${hostName}:${port}`; - if (databaseName) { - const encodeDatabaseName = encodeURIComponent(databaseName); - connectionString += `/${encodeDatabaseName}`; - } - return connectionString; +export function copyPostgresConnectionString( + hostName: string, + port: string = postgresDefaultPort, + username?: string | undefined, + password?: string | undefined, + databaseName?: string | undefined +): string { + let connectionString: string = `postgres://`; + if (username) { + const encodedUsername = encodeURIComponent(username); + if (password) { + const encodedPassword = encodeURIComponent(password); + const encodedPasswordWithQuotes = "'" + encodedPassword + "'"; + connectionString += `${encodedUsername}:${encodedPasswordWithQuotes}@`; + } else { + connectionString += `${encodedUsername}@`; + } + } + connectionString += `${hostName}:${port}`; + if (databaseName) { + const encodeDatabaseName = encodeURIComponent(databaseName); + connectionString += `/${encodeDatabaseName}`; + } + return connectionString; } export class ParsedPostgresConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public username: string | undefined; - public password: string | undefined; - public readonly port: string; + public readonly hostName: string; + public username: string | undefined; + public password: string | undefined; + public readonly port: string; - constructor(connectionString: string, config: ConnectionOptions) { - super(connectionString, config.database ? config.database : undefined); - this.hostName = nonNullProp(config, 'host'); - this.port = config.port ? config.port : `${postgresDefaultPort}`; - this.username = config.user; - this.password = config.password; - } + constructor(connectionString: string, config: ConnectionOptions) { + super(connectionString, config.database ? config.database : undefined); + this.hostName = nonNullProp(config, "host"); + this.port = config.port ? config.port : `${postgresDefaultPort}`; + this.username = config.user; + this.password = config.password; + } } diff --git a/Source/postgres/postgresConstants.ts b/Source/postgres/postgresConstants.ts index 9bcf15144..f94f58a25 100644 --- a/Source/postgres/postgresConstants.ts +++ b/Source/postgres/postgresConstants.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const invalidCredentialsErrorType: string = '28P01'; -export const firewallNotConfiguredErrorType: string = '28000'; -export const timeoutErrorType = 'ETIMEDOUT'; +export const invalidCredentialsErrorType: string = "28P01"; +export const firewallNotConfiguredErrorType: string = "28000"; +export const timeoutErrorType = "ETIMEDOUT"; diff --git a/Source/postgres/runPostgresQuery.ts b/Source/postgres/runPostgresQuery.ts index b7d325364..ce2a67c7b 100644 --- a/Source/postgres/runPostgresQuery.ts +++ b/Source/postgres/runPostgresQuery.ts @@ -5,15 +5,18 @@ import { Client, ClientConfig, QueryResult } from "pg"; -export async function runPostgresQuery(clientConfig: ClientConfig, query: string): Promise { - const client: Client = new Client(clientConfig); - try { - await client.connect(); - return await client.query(query); - } finally { - await client.end(); - } +export async function runPostgresQuery( + clientConfig: ClientConfig, + query: string +): Promise { + const client: Client = new Client(clientConfig); + try { + await client.connect(); + return await client.query(query); + } finally { + await client.end(); + } } export function wrapArgInQuotes(input: string): string { - return `"${input}"`; + return `"${input}"`; } diff --git a/Source/postgres/services/PostgresCodeLensProvider.ts b/Source/postgres/services/PostgresCodeLensProvider.ts index 5d075eb3c..d0d6bfe39 100644 --- a/Source/postgres/services/PostgresCodeLensProvider.ts +++ b/Source/postgres/services/PostgresCodeLensProvider.ts @@ -3,64 +3,88 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; -import { CodeLens, CodeLensProvider, Event, EventEmitter, Position, ProviderResult, Range } from "vscode"; +import { + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import { + CodeLens, + CodeLensProvider, + Event, + EventEmitter, + Position, + ProviderResult, + Range, +} from "vscode"; import { localize } from "../../utils/localize"; export class PostgresCodeLensProvider implements CodeLensProvider { - private _onDidChangeEmitter: EventEmitter = new EventEmitter(); - private _connectedDatabase: string | undefined; - private _connectedDatabaseInitialized: boolean; + private _onDidChangeEmitter: EventEmitter = new EventEmitter(); + private _connectedDatabase: string | undefined; + private _connectedDatabaseInitialized: boolean; - public get onDidChangeCodeLenses(): Event { - return this._onDidChangeEmitter.event; - } + public get onDidChangeCodeLenses(): Event { + return this._onDidChangeEmitter.event; + } - public setConnectedDatabase(database: string | undefined): void { - this._connectedDatabase = database; - this._connectedDatabaseInitialized = true; - this._onDidChangeEmitter.fire(); - } + public setConnectedDatabase(database: string | undefined): void { + this._connectedDatabase = database; + this._connectedDatabaseInitialized = true; + this._onDidChangeEmitter.fire(); + } - public provideCodeLenses(): ProviderResult { - return callWithTelemetryAndErrorHandling("postgreSQL.provideCodeLenses", (context: IActionContext) => { - // Suppress except for errors - this can fire on every keystroke - context.telemetry.suppressIfSuccessful = true; + public provideCodeLenses(): ProviderResult { + return callWithTelemetryAndErrorHandling( + "postgreSQL.provideCodeLenses", + (context: IActionContext) => { + // Suppress except for errors - this can fire on every keystroke + context.telemetry.suppressIfSuccessful = true; - const isInitialized = this._connectedDatabaseInitialized; - const isConnected = !!this._connectedDatabase; - const database = isConnected && this._connectedDatabase; - const lenses: CodeLens[] = []; + const isInitialized = this._connectedDatabaseInitialized; + const isConnected = !!this._connectedDatabase; + const database = isConnected && this._connectedDatabase; + const lenses: CodeLens[] = []; - let title: string; - if (!isInitialized) { - title = localize('initializing', 'Initializing...'); - } else if (isConnected) { - title = localize('connectedToDatabase', 'Connected to "{0}"', database); - } else { - title = localize('connectToDatabase', 'Connect to a database'); - } + let title: string; + if (!isInitialized) { + title = localize("initializing", "Initializing..."); + } else if (isConnected) { + title = localize( + "connectedToDatabase", + 'Connected to "{0}"', + database + ); + } else { + title = localize( + "connectToDatabase", + "Connect to a database" + ); + } - // Allow displaying and changing connected database - lenses.push({ - command: { - title, - command: isInitialized && 'postgreSQL.connectDatabase' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); + // Allow displaying and changing connected database + lenses.push({ + command: { + title, + command: isInitialized && "postgreSQL.connectDatabase", + }, + range: new Range(new Position(0, 0), new Position(0, 0)), + }); - if (isConnected) { - lenses.push({ - command: { - title: 'Execute Query', - command: 'postgreSQL.executeQuery' - }, - range: new Range(new Position(0, 0), new Position(0, 0)) - }); - } + if (isConnected) { + lenses.push({ + command: { + title: "Execute Query", + command: "postgreSQL.executeQuery", + }, + range: new Range( + new Position(0, 0), + new Position(0, 0) + ), + }); + } - return lenses; - }); - } + return lenses; + } + ); + } } diff --git a/Source/postgres/showPostgresQuery.ts b/Source/postgres/showPostgresQuery.ts index 7d6e2aa1d..4d1b277b4 100644 --- a/Source/postgres/showPostgresQuery.ts +++ b/Source/postgres/showPostgresQuery.ts @@ -3,12 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { postgresBaseFileName, postgresFileExtension } from '../constants'; -import * as vscodeUtil from '../utils/vscodeUtils'; +import { postgresBaseFileName, postgresFileExtension } from "../constants"; +import * as vscodeUtil from "../utils/vscodeUtils"; import { PostgresFunctionTreeItem } from "./tree/PostgresFunctionTreeItem"; import { PostgresStoredProcedureTreeItem } from "./tree/PostgresStoredProcedureTreeItem"; -export async function showPostgresQuery(treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem): Promise { - const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; - await vscodeUtil.showNewFile(treeItem.definition, fileName, postgresFileExtension); +export async function showPostgresQuery( + treeItem: PostgresFunctionTreeItem | PostgresStoredProcedureTreeItem +): Promise { + const fileName: string = `${treeItem.label}-${postgresBaseFileName}`; + await vscodeUtil.showNewFile( + treeItem.definition, + fileName, + postgresFileExtension + ); } diff --git a/Source/postgres/tree/ClientConfigFactory.ts b/Source/postgres/tree/ClientConfigFactory.ts index 271f5b92f..67a00710c 100644 --- a/Source/postgres/tree/ClientConfigFactory.ts +++ b/Source/postgres/tree/ClientConfigFactory.ts @@ -3,84 +3,123 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, parseError } from "@microsoft/vscode-azext-utils"; +import { + callWithTelemetryAndErrorHandling, + parseError, +} from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { getAzureAdUserSession, getTokenFunction } from "../../azureAccountUtils"; +import { + getAzureAdUserSession, + getTokenFunction, +} from "../../azureAccountUtils"; import { localize } from "../../utils/localize"; -import { PostgresClientConfigType, getClientConfigs, testClientConfig } from "../getClientConfig"; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType, timeoutErrorType } from "../postgresConstants"; +import { + PostgresClientConfigType, + getClientConfigs, + testClientConfig, +} from "../getClientConfig"; +import { + firewallNotConfiguredErrorType, + invalidCredentialsErrorType, + timeoutErrorType, +} from "../postgresConstants"; import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; -export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"; +export const postgresResourceType = + "https://ossrdbms-aad.database.windows.net/"; /** * Creates an object that can be used to execute a postgres query with connection test and telemetry. */ export class PostgresClientConfigFactory { - public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{ - type: "azureAd" | "password" | "connectionString", - clientConfig: ClientConfig - }> { - const parsedConnectionString = await treeItem.getFullConnectionString(); - const azureUserSession = await getAzureAdUserSession(); + public static async getClientConfigFromNode( + treeItem: PostgresServerTreeItem, + databaseName: string + ): Promise<{ + type: "azureAd" | "password" | "connectionString"; + clientConfig: ClientConfig; + }> { + const parsedConnectionString = await treeItem.getFullConnectionString(); + const azureUserSession = await getAzureAdUserSession(); - let hasSubscription: boolean = false; - let tokenFunction: (() => Promise) | undefined = undefined; - try { - const subscription = treeItem.subscription; - hasSubscription = true; - tokenFunction = getTokenFunction(subscription.credentials, postgresResourceType); - } catch (error) { - hasSubscription = false; - } - const clientConfigs = await getClientConfigs( - parsedConnectionString, - treeItem.serverType, - hasSubscription, - databaseName, - azureUserSession?.userId, - tokenFunction - ); + let hasSubscription: boolean = false; + let tokenFunction: (() => Promise) | undefined = undefined; + try { + const subscription = treeItem.subscription; + hasSubscription = true; + tokenFunction = getTokenFunction( + subscription.credentials, + postgresResourceType + ); + } catch (error) { + hasSubscription = false; + } + const clientConfigs = await getClientConfigs( + parsedConnectionString, + treeItem.serverType, + hasSubscription, + databaseName, + azureUserSession?.userId, + tokenFunction + ); - const clientConfigTypeOrder: PostgresClientConfigType[] = ["azureAd", "password", "connectionString"]; + const clientConfigTypeOrder: PostgresClientConfigType[] = [ + "azureAd", + "password", + "connectionString", + ]; - for (const clientConfigType of clientConfigTypeOrder) { - const clientConfig: ClientConfig | undefined = clientConfigs[clientConfigType]; - if (!clientConfig) { - continue; - } + for (const clientConfigType of clientConfigTypeOrder) { + const clientConfig: ClientConfig | undefined = + clientConfigs[clientConfigType]; + if (!clientConfig) { + continue; + } - try { - await callWithTelemetryAndErrorHandling("postgreSQL.testClientConfig", async (context) => { - context.errorHandling.rethrow = true; - context.errorHandling.suppressDisplay = true; - context.telemetry.properties.clientConfigType = clientConfigType; - await testClientConfig(clientConfig); - }); - return { - type: clientConfigType, - clientConfig - }; - } catch (error) { - const parsedError = parseError(error); - if (parsedError.errorType === invalidCredentialsErrorType) { - // If the client config failed with invalid credential error, skip and try the next available one. - } else if (parsedError.errorType === firewallNotConfiguredErrorType || parsedError.errorType === timeoutErrorType) { - // The time out error are common when the firewall rules doesn't grant access from the current IP address. - // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. - throw { - message: localize("mustConfigureFirewall", 'Must configure firewall from Azure Portal to grant access.'), - code: firewallNotConfiguredErrorType - }; - } else { - throw error; - } - } - } + try { + await callWithTelemetryAndErrorHandling( + "postgreSQL.testClientConfig", + async (context) => { + context.errorHandling.rethrow = true; + context.errorHandling.suppressDisplay = true; + context.telemetry.properties.clientConfigType = + clientConfigType; + await testClientConfig(clientConfig); + } + ); + return { + type: clientConfigType, + clientConfig, + }; + } catch (error) { + const parsedError = parseError(error); + if (parsedError.errorType === invalidCredentialsErrorType) { + // If the client config failed with invalid credential error, skip and try the next available one. + } else if ( + parsedError.errorType === firewallNotConfiguredErrorType || + parsedError.errorType === timeoutErrorType + ) { + // The time out error are common when the firewall rules doesn't grant access from the current IP address. + // If the client is blocked by the firewall, let the user go to Azure Portal to grant access. + throw { + message: localize( + "mustConfigureFirewall", + "Must configure firewall from Azure Portal to grant access." + ), + code: firewallNotConfiguredErrorType, + }; + } else { + throw error; + } + } + } - throw { - message: localize('mustEnterCredentials', 'Must enter credentials to connect to server.'), - code: invalidCredentialsErrorType - }; - } + throw { + message: localize( + "mustEnterCredentials", + "Must enter credentials to connect to server." + ), + code: invalidCredentialsErrorType, + }; + } } diff --git a/Source/postgres/tree/PostgresColumnTreeItem.ts b/Source/postgres/tree/PostgresColumnTreeItem.ts index d284c8122..aedfa46f2 100644 --- a/Source/postgres/tree/PostgresColumnTreeItem.ts +++ b/Source/postgres/tree/PostgresColumnTreeItem.ts @@ -3,31 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; +import { AzExtTreeItem, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresColumnTreeItem extends AzExtTreeItem { - public static contextValue: string = "postgresColumn"; - public readonly contextValue: string = PostgresColumnTreeItem.contextValue; - public readonly columnName: string; - public readonly parent: PostgresTableTreeItem; + public static contextValue: string = "postgresColumn"; + public readonly contextValue: string = PostgresColumnTreeItem.contextValue; + public readonly columnName: string; + public readonly parent: PostgresTableTreeItem; - constructor(parent: PostgresTableTreeItem, columnName: string) { - super(parent); - this.columnName = columnName; - } + constructor(parent: PostgresTableTreeItem, columnName: string) { + super(parent); + this.columnName = columnName; + } - public get id(): string { - return this.columnName; - } + public get id(): string { + return this.columnName; + } - public get label(): string { - return this.columnName; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('split-horizontal'); - } + public get label(): string { + return this.columnName; + } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("split-horizontal"); + } } diff --git a/Source/postgres/tree/PostgresDatabaseTreeItem.ts b/Source/postgres/tree/PostgresDatabaseTreeItem.ts index 05f7a4412..e9463d0bc 100644 --- a/Source/postgres/tree/PostgresDatabaseTreeItem.ts +++ b/Source/postgres/tree/PostgresDatabaseTreeItem.ts @@ -4,112 +4,178 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line import/no-internal-modules -import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { ThemeIcon } from 'vscode'; -import { ext } from '../../extensionVariables'; -import { localize } from '../../utils/localize'; -import { firewallNotConfiguredErrorType, invalidCredentialsErrorType } from '../postgresConstants'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresServerTreeItem } from './PostgresServerTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import { + AzExtParentTreeItem, + AzExtTreeItem, + createContextValue, + GenericTreeItem, + IActionContext, + IParsedError, + parseError, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { ThemeIcon } from "vscode"; +import { ext } from "../../extensionVariables"; +import { localize } from "../../utils/localize"; +import { + firewallNotConfiguredErrorType, + invalidCredentialsErrorType, +} from "../postgresConstants"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresClientConfigFactory } from "./ClientConfigFactory"; +import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; +import { PostgresServerTreeItem } from "./PostgresServerTreeItem"; +import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; export class PostgresDatabaseTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresDatabase"; - public contextValue: string = PostgresDatabaseTreeItem.contextValue; - public readonly childTypeLabel: string = "Resource Type"; - public readonly databaseName: string; - public readonly parent: PostgresServerTreeItem; - public autoSelectInTreeItemPicker: boolean = true; - public isShowingPasswordWarning: boolean; + public static contextValue: string = "postgresDatabase"; + public contextValue: string = PostgresDatabaseTreeItem.contextValue; + public readonly childTypeLabel: string = "Resource Type"; + public readonly databaseName: string; + public readonly parent: PostgresServerTreeItem; + public autoSelectInTreeItemPicker: boolean = true; + public isShowingPasswordWarning: boolean; - constructor(parent: PostgresServerTreeItem, databaseName: string) { - super(parent); - this.databaseName = databaseName; - this.isShowingPasswordWarning = false; - } + constructor(parent: PostgresServerTreeItem, databaseName: string) { + super(parent); + this.databaseName = databaseName; + this.isShowingPasswordWarning = false; + } - public get label(): string { - return this.databaseName; - } + public get label(): string { + return this.databaseName; + } - public get description(): string { - return ext.connectedPostgresDB?.fullId === this.fullId ? localize('connected', 'Connected') : ''; - } + public get description(): string { + return ext.connectedPostgresDB?.fullId === this.fullId + ? localize("connected", "Connected") + : ""; + } - public get id(): string { - return this.databaseName; - } + public get id(): string { + return this.databaseName; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('database'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("database"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); - if (!isFirewallRuleSet) { - const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresFirewall', - label: localize('configureFirewall', 'Configure firewall to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.configureFirewall' - }); - firewallTreeItem.commandArgs = [this.parent]; - return [firewallTreeItem]; - } + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + const isFirewallRuleSet = await this.parent.isFirewallRuleSet(context); + if (!isFirewallRuleSet) { + const firewallTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: "postgresFirewall", + label: localize( + "configureFirewall", + 'Configure firewall to connect to "{0}"...', + this.parent.label + ), + commandId: "postgreSQL.configureFirewall", + }); + firewallTreeItem.commandArgs = [this.parent]; + return [firewallTreeItem]; + } - try { - const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - if (type === "password") { - void this.showPasswordWarning(context); - } - const children: AzExtTreeItem[] = [ - new PostgresFunctionsTreeItem(this, clientConfig), - new PostgresTablesTreeItem(this, clientConfig) - ]; + try { + const { type, clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this.parent, + this.databaseName + ); + if (type === "password") { + void this.showPasswordWarning(context); + } + const children: AzExtTreeItem[] = [ + new PostgresFunctionsTreeItem(this, clientConfig), + new PostgresTablesTreeItem(this, clientConfig), + ]; - if (await this.parent.supportsStoredProcedures(clientConfig)) { - children.push(new PostgresStoredProceduresTreeItem(this, clientConfig)); - } + if (await this.parent.supportsStoredProcedures(clientConfig)) { + children.push( + new PostgresStoredProceduresTreeItem(this, clientConfig) + ); + } - return children; - } catch (error) { - const parsedError: IParsedError = parseError(error); + return children; + } catch (error) { + const parsedError: IParsedError = parseError(error); - if (this.parent.azureName && parsedError.errorType === invalidCredentialsErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'postgresCredentials', - label: localize('enterCredentials', 'Enter server credentials to connect to "{0}"...', this.parent.label), - commandId: 'postgreSQL.enterCredentials' - }); - credentialsTreeItem.commandArgs = [this.parent]; - return [credentialsTreeItem]; - } else if (this.parent.azureName && parsedError.errorType === firewallNotConfiguredErrorType) { - void context.ui.showWarningMessage(localize('couldNotConnect', 'Could not connect to "{0}": {1}', this.parent.label, parsedError.message), { stepName: 'loadPostgresDatabases' }); - return []; - } else { - throw error; - } - } - } + if ( + this.parent.azureName && + parsedError.errorType === invalidCredentialsErrorType + ) { + void context.ui.showWarningMessage( + localize( + "couldNotConnect", + 'Could not connect to "{0}": {1}', + this.parent.label, + parsedError.message + ), + { stepName: "loadPostgresDatabases" } + ); + const credentialsTreeItem: AzExtTreeItem = new GenericTreeItem( + this, + { + contextValue: "postgresCredentials", + label: localize( + "enterCredentials", + 'Enter server credentials to connect to "{0}"...', + this.parent.label + ), + commandId: "postgreSQL.enterCredentials", + } + ); + credentialsTreeItem.commandArgs = [this.parent]; + return [credentialsTreeItem]; + } else if ( + this.parent.azureName && + parsedError.errorType === firewallNotConfiguredErrorType + ) { + void context.ui.showWarningMessage( + localize( + "couldNotConnect", + 'Could not connect to "{0}": {1}', + this.parent.label, + parsedError.message + ), + { stepName: "loadPostgresDatabases" } + ); + return []; + } else { + throw error; + } + } + } - public async deleteTreeItemImpl(): Promise { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName); - await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`); - } + public async deleteTreeItemImpl(): Promise { + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this.parent, + this.databaseName + ); + await runPostgresQuery( + clientConfig, + `Drop Database ${wrapArgInQuotes(this.databaseName)};` + ); + } - private async showPasswordWarning(context: IActionContext): Promise { - if (this.isShowingPasswordWarning) { - return; - } - this.isShowingPasswordWarning = true; - this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]); - await this.refresh(context); - } + private async showPasswordWarning(context: IActionContext): Promise { + if (this.isShowingPasswordWarning) { + return; + } + this.isShowingPasswordWarning = true; + this.contextValue = createContextValue([ + PostgresDatabaseTreeItem.contextValue, + "usesPassword", + ]); + await this.refresh(context); + } } diff --git a/Source/postgres/tree/PostgresFunctionTreeItem.ts b/Source/postgres/tree/PostgresFunctionTreeItem.ts index 0a26bf3f9..d7bc46a16 100644 --- a/Source/postgres/tree/PostgresFunctionTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionTreeItem.ts @@ -10,39 +10,49 @@ import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; export class PostgresFunctionTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresFunction'; - public readonly contextValue: string = PostgresFunctionTreeItem.contextValue; - public readonly parent: PostgresFunctionsTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = "postgresFunction"; + public readonly contextValue: string = + PostgresFunctionTreeItem.contextValue; + public readonly parent: PostgresFunctionsTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor(parent: PostgresFunctionsTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openFunction'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor( + parent: PostgresFunctionsTreeItem, + row: IPostgresProceduresQueryRow, + isDuplicate: boolean + ) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = "postgreSQL.openFunction"; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("symbol-function"); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${this.args});`); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `DROP FUNCTION ${this.schema}.${wrapArgInQuotes(this.name)}(${ + this.args + });` + ); + } } diff --git a/Source/postgres/tree/PostgresFunctionsTreeItem.ts b/Source/postgres/tree/PostgresFunctionsTreeItem.ts index 7d3904e83..8f373ab95 100644 --- a/Source/postgres/tree/PostgresFunctionsTreeItem.ts +++ b/Source/postgres/tree/PostgresFunctionsTreeItem.ts @@ -4,43 +4,51 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; +import { ClientConfig } from "pg"; +import { ThemeIcon } from "vscode"; +import { + getPostgresProcedureQueryRows, + IPostgresProceduresQueryRow, +} from "../getPostgresProcedureQueryRows"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; +import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; export class PostgresFunctionsTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresFunctions'; - public readonly contextValue: string = PostgresFunctionsTreeItem.contextValue; - public readonly label: string = 'Functions'; - public readonly childTypeLabel: string = 'Function'; - public suppressMaskLabel = true; + public static contextValue: string = "postgresFunctions"; + public readonly contextValue: string = + PostgresFunctionsTreeItem.contextValue; + public readonly label: string = "Functions"; + public readonly childTypeLabel: string = "Function"; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('symbol-function'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("symbol-function"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresFunctionTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } + public async loadMoreChildrenImpl(): Promise { + const rows: IPostgresProceduresQueryRow[] = + await getPostgresProcedureQueryRows(this); + return rows.map( + (row) => + new PostgresFunctionTreeItem( + this, + row, + this.isDuplicateResource(row.name) + ) + ); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresFunctionTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresFunctionTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts index b93cc9450..40e4d07c5 100644 --- a/Source/postgres/tree/PostgresResourcesTreeItemBase.ts +++ b/Source/postgres/tree/PostgresResourcesTreeItemBase.ts @@ -9,19 +9,19 @@ import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; // Base class for Postgres tree items whose children are individual resources export abstract class PostgresResourcesTreeItemBase extends AzExtParentTreeItem { - public parent: PostgresDatabaseTreeItem; - public clientConfig: ClientConfig; - public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas + public parent: PostgresDatabaseTreeItem; + public clientConfig: ClientConfig; + public resourcesAndSchemas: { [key: string]: string[] }; // Resource name to list of schemas - public addResourcesAndSchemasEntry(name: string, schema: string): void { - if (this.resourcesAndSchemas[name]) { - this.resourcesAndSchemas[name].push(schema); - } else { - this.resourcesAndSchemas[name] = [schema]; - } - } + public addResourcesAndSchemasEntry(name: string, schema: string): void { + if (this.resourcesAndSchemas[name]) { + this.resourcesAndSchemas[name].push(schema); + } else { + this.resourcesAndSchemas[name] = [schema]; + } + } - public isDuplicateResource(name: string): boolean { - return this.resourcesAndSchemas[name].length > 1; - } + public isDuplicateResource(name: string): boolean { + return this.resourcesAndSchemas[name].length > 1; + } } diff --git a/Source/postgres/tree/PostgresServerTreeItem.ts b/Source/postgres/tree/PostgresServerTreeItem.ts index 20e7dbe76..1ffc11403 100644 --- a/Source/postgres/tree/PostgresServerTreeItem.ts +++ b/Source/postgres/tree/PostgresServerTreeItem.ts @@ -3,250 +3,383 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as SingleModels from '@azure/arm-postgresql'; -import * as FlexibleModels from '@azure/arm-postgresql-flexible'; -import { getResourceGroupFromId, parseAzureResourceId, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils'; -import { ClientConfig } from 'pg'; -import { SemVer, coerce, gte } from 'semver'; -import * as vscode from 'vscode'; -import { getThemeAgnosticIconPath, postgresDefaultDatabase } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { isIpInRanges } from '../../utils/getIp'; -import { getSecretStorageKey } from '../../utils/getSecretStorageKey'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../abstract/AbstractPostgresClient'; -import { PostgresAbstractServer, PostgresServerType } from '../abstract/models'; -import { getPublicIp } from '../commands/configurePostgresFirewall'; -import { ParsedPostgresConnectionString } from '../postgresConnectionStrings'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresClientConfigFactory } from './ClientConfigFactory'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresFunctionTreeItem } from './PostgresFunctionTreeItem'; -import { PostgresFunctionsTreeItem } from './PostgresFunctionsTreeItem'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; -import { PostgresStoredProceduresTreeItem } from './PostgresStoredProceduresTreeItem'; -import { PostgresTableTreeItem } from './PostgresTableTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import * as SingleModels from "@azure/arm-postgresql"; +import * as FlexibleModels from "@azure/arm-postgresql-flexible"; +import { + getResourceGroupFromId, + parseAzureResourceId, + uiUtils, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + IActionContext, + ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import { ClientConfig } from "pg"; +import { SemVer, coerce, gte } from "semver"; +import * as vscode from "vscode"; +import { + getThemeAgnosticIconPath, + postgresDefaultDatabase, +} from "../../constants"; +import { ext } from "../../extensionVariables"; +import { isIpInRanges } from "../../utils/getIp"; +import { getSecretStorageKey } from "../../utils/getSecretStorageKey"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../abstract/AbstractPostgresClient"; +import { PostgresAbstractServer, PostgresServerType } from "../abstract/models"; +import { getPublicIp } from "../commands/configurePostgresFirewall"; +import { ParsedPostgresConnectionString } from "../postgresConnectionStrings"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresClientConfigFactory } from "./ClientConfigFactory"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { PostgresFunctionTreeItem } from "./PostgresFunctionTreeItem"; +import { PostgresFunctionsTreeItem } from "./PostgresFunctionsTreeItem"; +import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; +import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; +import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; interface IPersistedServer { - id: string; - username: string; + id: string; + username: string; } export class PostgresServerTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresServer"; - public static serviceName: string = "ms-azuretools.vscode-azuredatabases.postgresPasswords"; - public readonly contextValue: string = PostgresServerTreeItem.contextValue; - public readonly childTypeLabel: string = "Database"; - public readonly serverType: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - constructor(parent: AzExtParentTreeItem, connectionString: ParsedPostgresConnectionString, server?: PostgresAbstractServer) { - super(parent); - this.partialConnectionString = connectionString; - if (server) { - this.azureId = server?.id; - this.serverVersion = server?.version; - this.resourceGroup = getResourceGroupFromId(this.fullId); - this.azureName = server?.name; - this.serverType = parseAzureResourceId(this.fullId).provider.toLowerCase().includes('flexible') ? PostgresServerType.Flexible : PostgresServerType.Single; - } - this.valuesToMask.push(connectionString.accountId, connectionString.connectionString, connectionString.fullId, connectionString.hostName, connectionString.port); - if (connectionString.databaseName) { - this.valuesToMask.push(connectionString.databaseName); - } - } - - public get iconPath(): string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri } { - return getThemeAgnosticIconPath('PostgresServer.svg'); - } - - public get label(): string { - return this.azureName ? this.azureName : this.partialConnectionString.fullId; - } - - public get id(): string { - if (this.azureId) { - return this.azureId; - } - return this.partialConnectionString.fullId; - } - - public get description(): string | undefined { - switch (this.serverType) { - case PostgresServerType.Flexible: - return "PostgreSQL Flexible"; - case PostgresServerType.Single: - return "PostgreSQL Single"; - default: - return "PostgreSQL"; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - context.telemetry.properties.serverType = this.serverType; - let dbNames: (string | undefined)[]; - if (this.azureName) { - const client: AbstractPostgresClient = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const listOfDatabases: (SingleModels.Database | FlexibleModels.Database)[] = await uiUtils.listAllIterator(client.databases.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName'))); - dbNames = listOfDatabases.map(db => db.name); - } else if (this.partialConnectionString.databaseName) { - dbNames = [this.partialConnectionString.databaseName]; - } else { - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase); - const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; - const queryResult = await runPostgresQuery(clientConfig, query); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - dbNames = queryResult.rows.map(db => db?.datname); - } - - return this.createTreeItemsWithErrorHandling( - dbNames, - 'invalidPostgresServer', - dbName => dbName && !['azure_maintenance', 'azure_sys'].includes(dbName) ? new PostgresDatabaseTreeItem(this, dbName) : undefined, - dbName => dbName - ); - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - case PostgresDatabaseTreeItem.contextValue: - case PostgresTablesTreeItem.contextValue: - case PostgresTableTreeItem.contextValue: - case PostgresFunctionsTreeItem.contextValue: - case PostgresFunctionTreeItem.contextValue: - case PostgresStoredProceduresTreeItem.contextValue: - case PostgresStoredProcedureTreeItem.contextValue: - return true; - default: - return false; - } - } - - public async createChildImpl(context: ICreateChildImplContext): Promise { - if (this.partialConnectionString.databaseName) { - throw new Error(localize('noPermissionToCreateDatabase', `This attached account does not have permissions to create a database.`)); - } - const getChildrenTask: Promise = this.getCachedChildren(context); - const databaseName = await context.ui.showInputBox({ - placeHolder: "Database Name", - prompt: "Enter the name of the database", - stepName: 'createPostgresDatabase', - validateInput: (name: string) => validateDatabaseName(name, getChildrenTask) - }); - const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName); - context.showCreatingTreeItem(databaseName); - await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`); - return new PostgresDatabaseTreeItem(this, databaseName); - } - - public async deleteTreeItemImpl(context: IActionContext): Promise { - const client = await createAbstractPostgresClient(this.serverType, [context, this.subscription]); - const deletingMessage: string = `Deleting server "${this.label}"...`; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => { - await client.servers.beginDeleteAndWait(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')); - await this.deletePostgresCredentials(); - - const deleteMessage: string = localize("deleteServerMsg", 'Successfully deleted server "{0}".', this.label); - void vscode.window.showInformationMessage(deleteMessage); - ext.outputChannel.appendLog(deleteMessage); - }); - } - - public setCredentials(username: string, password: string): void { - this.partialConnectionString.username = username; - this.partialConnectionString.password = password; - } - - public async supportsStoredProcedures(clientConfig: ClientConfig): Promise { - // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer - if (!this.serverVersion) { - const result = await runPostgresQuery(clientConfig, `SHOW server_version;`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - this.serverVersion = result.rows[0].server_version; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - const version: SemVer | null = coerce(this.serverVersion); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return gte(version, '11.0.0'); - } - - public async deletePostgresCredentials(): Promise { - const serviceName: string = PostgresServerTreeItem.serviceName; - const storedValue: string | undefined = ext.context.globalState.get(serviceName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - let servers: IPersistedServer[] = storedValue ? JSON.parse(storedValue) : []; - - // Remove this server from the cache - servers = servers.filter((server: IPersistedServer) => { return server.id !== this.id; }); - - await ext.context.globalState.update(serviceName, JSON.stringify(servers)); - await ext.secretStorage.delete(getSecretStorageKey(serviceName, this.id)); - } - - public async getFullConnectionString(): Promise { - - if (this.azureId && !(this.partialConnectionString.username && this.partialConnectionString.password)) { - const storedValue: string | undefined = ext.context.globalState.get(PostgresServerTreeItem.serviceName); - if (storedValue) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const servers: IPersistedServer[] = JSON.parse(storedValue); - for (const server of servers) { - if (server.id === this.id) { - this.partialConnectionString.username = server.username; - // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials - this.partialConnectionString.password = await ext.secretStorage.get(getSecretStorageKey(PostgresServerTreeItem.serviceName, this.id)) || undefined; - break; - } - } - } - } - return this.partialConnectionString; - } - - /** - * @returns true if we believe the firewall allows the current IP to connect to database server. - */ - public async isFirewallRuleSet(context: IActionContext): Promise { - try { - const serverType: PostgresServerType = nonNullProp(this, 'serverType'); - const client: AbstractPostgresClient = await createAbstractPostgresClient(serverType, [context, this.subscription]); - const results: SingleModels.FirewallRule[] = (await uiUtils.listAllIterator(client.firewallRules.listByServer(nonNullProp(this, 'resourceGroup'), nonNullProp(this, 'azureName')))); - const publicIp: string = await getPublicIp(context); - return isIpInRanges(publicIp, results); - } catch (error) { - // We cannot get the firewall rules from attached databases because we cannot get the subscription object. - // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. - return true; - } - } + public static contextValue: string = "postgresServer"; + public static serviceName: string = + "ms-azuretools.vscode-azuredatabases.postgresPasswords"; + public readonly contextValue: string = PostgresServerTreeItem.contextValue; + public readonly childTypeLabel: string = "Database"; + public readonly serverType: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + constructor( + parent: AzExtParentTreeItem, + connectionString: ParsedPostgresConnectionString, + server?: PostgresAbstractServer + ) { + super(parent); + this.partialConnectionString = connectionString; + if (server) { + this.azureId = server?.id; + this.serverVersion = server?.version; + this.resourceGroup = getResourceGroupFromId(this.fullId); + this.azureName = server?.name; + this.serverType = parseAzureResourceId(this.fullId) + .provider.toLowerCase() + .includes("flexible") + ? PostgresServerType.Flexible + : PostgresServerType.Single; + } + this.valuesToMask.push( + connectionString.accountId, + connectionString.connectionString, + connectionString.fullId, + connectionString.hostName, + connectionString.port + ); + if (connectionString.databaseName) { + this.valuesToMask.push(connectionString.databaseName); + } + } + + public get iconPath(): + | string + | vscode.Uri + | { light: string | vscode.Uri; dark: string | vscode.Uri } { + return getThemeAgnosticIconPath("PostgresServer.svg"); + } + + public get label(): string { + return this.azureName + ? this.azureName + : this.partialConnectionString.fullId; + } + + public get id(): string { + if (this.azureId) { + return this.azureId; + } + return this.partialConnectionString.fullId; + } + + public get description(): string | undefined { + switch (this.serverType) { + case PostgresServerType.Flexible: + return "PostgreSQL Flexible"; + case PostgresServerType.Single: + return "PostgreSQL Single"; + default: + return "PostgreSQL"; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + context.telemetry.properties.serverType = this.serverType; + let dbNames: (string | undefined)[]; + if (this.azureName) { + const client: AbstractPostgresClient = + await createAbstractPostgresClient(this.serverType, [ + context, + this.subscription, + ]); + const listOfDatabases: ( + | SingleModels.Database + | FlexibleModels.Database + )[] = await uiUtils.listAllIterator( + client.databases.listByServer( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ) + ); + dbNames = listOfDatabases.map((db) => db.name); + } else if (this.partialConnectionString.databaseName) { + dbNames = [this.partialConnectionString.databaseName]; + } else { + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this, + postgresDefaultDatabase + ); + const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`; + const queryResult = await runPostgresQuery(clientConfig, query); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + dbNames = queryResult.rows.map((db) => db?.datname); + } + + return this.createTreeItemsWithErrorHandling( + dbNames, + "invalidPostgresServer", + (dbName) => + dbName && !["azure_maintenance", "azure_sys"].includes(dbName) + ? new PostgresDatabaseTreeItem(this, dbName) + : undefined, + (dbName) => dbName + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + case PostgresDatabaseTreeItem.contextValue: + case PostgresTablesTreeItem.contextValue: + case PostgresTableTreeItem.contextValue: + case PostgresFunctionsTreeItem.contextValue: + case PostgresFunctionTreeItem.contextValue: + case PostgresStoredProceduresTreeItem.contextValue: + case PostgresStoredProcedureTreeItem.contextValue: + return true; + default: + return false; + } + } + + public async createChildImpl( + context: ICreateChildImplContext + ): Promise { + if (this.partialConnectionString.databaseName) { + throw new Error( + localize( + "noPermissionToCreateDatabase", + `This attached account does not have permissions to create a database.` + ) + ); + } + const getChildrenTask: Promise = + this.getCachedChildren(context); + const databaseName = await context.ui.showInputBox({ + placeHolder: "Database Name", + prompt: "Enter the name of the database", + stepName: "createPostgresDatabase", + validateInput: (name: string) => + validateDatabaseName(name, getChildrenTask), + }); + const { clientConfig } = + await PostgresClientConfigFactory.getClientConfigFromNode( + this, + databaseName + ); + context.showCreatingTreeItem(databaseName); + await runPostgresQuery( + clientConfig, + `Create Database ${wrapArgInQuotes(databaseName)};` + ); + return new PostgresDatabaseTreeItem(this, databaseName); + } + + public async deleteTreeItemImpl(context: IActionContext): Promise { + const client = await createAbstractPostgresClient(this.serverType, [ + context, + this.subscription, + ]); + const deletingMessage: string = `Deleting server "${this.label}"...`; + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: deletingMessage, + }, + async () => { + await client.servers.beginDeleteAndWait( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ); + await this.deletePostgresCredentials(); + + const deleteMessage: string = localize( + "deleteServerMsg", + 'Successfully deleted server "{0}".', + this.label + ); + void vscode.window.showInformationMessage(deleteMessage); + ext.outputChannel.appendLog(deleteMessage); + } + ); + } + + public setCredentials(username: string, password: string): void { + this.partialConnectionString.username = username; + this.partialConnectionString.password = password; + } + + public async supportsStoredProcedures( + clientConfig: ClientConfig + ): Promise { + // `semver.gte` complains when a version doesn't have decimals (i.e. "10"), so attempt to convert version to SemVer + if (!this.serverVersion) { + const result = await runPostgresQuery( + clientConfig, + `SHOW server_version;` + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + this.serverVersion = result.rows[0].server_version; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + const version: SemVer | null = coerce(this.serverVersion); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call + return gte(version, "11.0.0"); + } + + public async deletePostgresCredentials(): Promise { + const serviceName: string = PostgresServerTreeItem.serviceName; + const storedValue: string | undefined = + ext.context.globalState.get(serviceName); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + let servers: IPersistedServer[] = storedValue + ? JSON.parse(storedValue) + : []; + + // Remove this server from the cache + servers = servers.filter((server: IPersistedServer) => { + return server.id !== this.id; + }); + + await ext.context.globalState.update( + serviceName, + JSON.stringify(servers) + ); + await ext.secretStorage.delete( + getSecretStorageKey(serviceName, this.id) + ); + } + + public async getFullConnectionString(): Promise { + if ( + this.azureId && + !( + this.partialConnectionString.username && + this.partialConnectionString.password + ) + ) { + const storedValue: string | undefined = ext.context.globalState.get( + PostgresServerTreeItem.serviceName + ); + if (storedValue) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const servers: IPersistedServer[] = JSON.parse(storedValue); + for (const server of servers) { + if (server.id === this.id) { + this.partialConnectionString.username = server.username; + // Migration from keytar isn't necessary, the user will automatically be prompted to reenter credentials + this.partialConnectionString.password = + (await ext.secretStorage.get( + getSecretStorageKey( + PostgresServerTreeItem.serviceName, + this.id + ) + )) || undefined; + break; + } + } + } + } + return this.partialConnectionString; + } + + /** + * @returns true if we believe the firewall allows the current IP to connect to database server. + */ + public async isFirewallRuleSet(context: IActionContext): Promise { + try { + const serverType: PostgresServerType = nonNullProp( + this, + "serverType" + ); + const client: AbstractPostgresClient = + await createAbstractPostgresClient(serverType, [ + context, + this.subscription, + ]); + const results: SingleModels.FirewallRule[] = + await uiUtils.listAllIterator( + client.firewallRules.listByServer( + nonNullProp(this, "resourceGroup"), + nonNullProp(this, "azureName") + ) + ); + const publicIp: string = await getPublicIp(context); + return isIpInRanges(publicIp, results); + } catch (error) { + // We cannot get the firewall rules from attached databases because we cannot get the subscription object. + // We assume the database server has configured the necessary firewall rules to allow connections from the current IP. + return true; + } + } } -async function validateDatabaseName(name: string, getChildrenTask: Promise): Promise { - if (!name) { - return localize('NameCannotBeEmpty', 'Name cannot be empty.'); - } - const currDatabaseList = await getChildrenTask; - const currDatabaseNames: string[] = []; - for (const db of currDatabaseList) { - if (db instanceof PostgresDatabaseTreeItem) { - currDatabaseNames.push(db.databaseName); - } - } - if (currDatabaseNames.includes(name)) { - return localize('NameExists', 'Database "{0}" already exists.', name); - } - return undefined; +async function validateDatabaseName( + name: string, + getChildrenTask: Promise +): Promise { + if (!name) { + return localize("NameCannotBeEmpty", "Name cannot be empty."); + } + const currDatabaseList = await getChildrenTask; + const currDatabaseNames: string[] = []; + for (const db of currDatabaseList) { + if (db instanceof PostgresDatabaseTreeItem) { + currDatabaseNames.push(db.databaseName); + } + } + if (currDatabaseNames.includes(name)) { + return localize("NameExists", 'Database "{0}" already exists.', name); + } + return undefined; } diff --git a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts index 503d0ae74..1c903d9e2 100644 --- a/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProcedureTreeItem.ts @@ -10,39 +10,47 @@ import { runPostgresQuery } from "../runPostgresQuery"; import { PostgresStoredProceduresTreeItem } from "./PostgresStoredProceduresTreeItem"; export class PostgresStoredProcedureTreeItem extends AzExtTreeItem { - public static contextValue: string = 'postgresStoredProcedure'; - public readonly contextValue: string = PostgresStoredProcedureTreeItem.contextValue; - public readonly parent: PostgresStoredProceduresTreeItem; - public readonly schema: string; - public readonly name: string; - public readonly args: string; - public readonly isDuplicate: boolean; - public definition: string; + public static contextValue: string = "postgresStoredProcedure"; + public readonly contextValue: string = + PostgresStoredProcedureTreeItem.contextValue; + public readonly parent: PostgresStoredProceduresTreeItem; + public readonly schema: string; + public readonly name: string; + public readonly args: string; + public readonly isDuplicate: boolean; + public definition: string; - constructor(parent: PostgresStoredProceduresTreeItem, row: IPostgresProceduresQueryRow, isDuplicate: boolean) { - super(parent); - this.schema = row.schema; - this.name = row.name; - this.id = String(row.oid); - this.commandId = 'postgreSQL.openStoredProcedure'; - this.args = row.args; - this.definition = row.definition; - this.isDuplicate = isDuplicate; - } + constructor( + parent: PostgresStoredProceduresTreeItem, + row: IPostgresProceduresQueryRow, + isDuplicate: boolean + ) { + super(parent); + this.schema = row.schema; + this.name = row.name; + this.id = String(row.oid); + this.commandId = "postgreSQL.openStoredProcedure"; + this.args = row.args; + this.definition = row.definition; + this.isDuplicate = isDuplicate; + } - public get label(): string { - return this.name; - } + public get label(): string { + return this.name; + } - public get description(): string | undefined { - return this.isDuplicate ? this.schema : undefined; - } + public get description(): string | undefined { + return this.isDuplicate ? this.schema : undefined; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("server-process"); + } - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});`); - } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `DROP PROCEDURE ${this.schema}.${this.name}(${this.args});` + ); + } } diff --git a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts index 1c516e00f..9525856f6 100644 --- a/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts +++ b/Source/postgres/tree/PostgresStoredProceduresTreeItem.ts @@ -4,43 +4,53 @@ *--------------------------------------------------------------------------------------------*/ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { ClientConfig } from 'pg'; -import { ThemeIcon } from 'vscode'; -import { getPostgresProcedureQueryRows, IPostgresProceduresQueryRow } from '../getPostgresProcedureQueryRows'; -import { PostgresDatabaseTreeItem } from './PostgresDatabaseTreeItem'; -import { PostgresResourcesTreeItemBase } from './PostgresResourcesTreeItemBase'; -import { PostgresStoredProcedureTreeItem } from './PostgresStoredProcedureTreeItem'; +import { ClientConfig } from "pg"; +import { ThemeIcon } from "vscode"; +import { + getPostgresProcedureQueryRows, + IPostgresProceduresQueryRow, +} from "../getPostgresProcedureQueryRows"; +import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; +import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; +import { PostgresStoredProcedureTreeItem } from "./PostgresStoredProcedureTreeItem"; export class PostgresStoredProceduresTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = 'postgresStoredProcedures'; - public readonly contextValue: string = PostgresStoredProceduresTreeItem.contextValue; - public readonly label: string = 'Stored Procedures'; - public readonly childTypeLabel: string = 'Stored Procedure'; - public suppressMaskLabel = true; + public static contextValue: string = "postgresStoredProcedures"; + public readonly contextValue: string = + PostgresStoredProceduresTreeItem.contextValue; + public readonly label: string = "Stored Procedures"; + public readonly childTypeLabel: string = "Stored Procedure"; + public suppressMaskLabel = true; - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('server-process'); - } + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("server-process"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(): Promise { - const rows: IPostgresProceduresQueryRow[] = await getPostgresProcedureQueryRows(this); - return rows.map(row => new PostgresStoredProcedureTreeItem( - this, - row, - this.isDuplicateResource(row.name) - )); - } + public async loadMoreChildrenImpl(): Promise< + PostgresStoredProcedureTreeItem[] + > { + const rows: IPostgresProceduresQueryRow[] = + await getPostgresProcedureQueryRows(this); + return rows.map( + (row) => + new PostgresStoredProcedureTreeItem( + this, + row, + this.isDuplicateResource(row.name) + ) + ); + } - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresStoredProcedureTreeItem.contextValue; - } + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresStoredProcedureTreeItem.contextValue; + } } diff --git a/Source/postgres/tree/PostgresTableTreeItem.ts b/Source/postgres/tree/PostgresTableTreeItem.ts index ef5d87c2c..fb844038b 100644 --- a/Source/postgres/tree/PostgresTableTreeItem.ts +++ b/Source/postgres/tree/PostgresTableTreeItem.ts @@ -3,54 +3,68 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtParentTreeItem, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { IPostgresTable } from '../getTables'; -import { runPostgresQuery, wrapArgInQuotes } from '../runPostgresQuery'; -import { PostgresColumnTreeItem } from './PostgresColumnTreeItem'; -import { PostgresTablesTreeItem } from './PostgresTablesTreeItem'; +import { + AzExtParentTreeItem, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { IPostgresTable } from "../getTables"; +import { runPostgresQuery, wrapArgInQuotes } from "../runPostgresQuery"; +import { PostgresColumnTreeItem } from "./PostgresColumnTreeItem"; +import { PostgresTablesTreeItem } from "./PostgresTablesTreeItem"; export class PostgresTableTreeItem extends AzExtParentTreeItem { - public static contextValue: string = "postgresTable"; - public readonly contextValue: string = PostgresTableTreeItem.contextValue; - public readonly table: IPostgresTable; - public readonly parent: PostgresTablesTreeItem; + public static contextValue: string = "postgresTable"; + public readonly contextValue: string = PostgresTableTreeItem.contextValue; + public readonly table: IPostgresTable; + public readonly parent: PostgresTablesTreeItem; - private _isDuplicate: boolean; + private _isDuplicate: boolean; - constructor(parent: PostgresTablesTreeItem, table: IPostgresTable, isDuplicate: boolean) { - super(parent); - this.table = table; - this._isDuplicate = isDuplicate; - } + constructor( + parent: PostgresTablesTreeItem, + table: IPostgresTable, + isDuplicate: boolean + ) { + super(parent); + this.table = table; + this._isDuplicate = isDuplicate; + } - public get id(): string { - return String(this.table.oid); - } + public get id(): string { + return String(this.table.oid); + } - public get label(): string { - return this.table.name; - } + public get label(): string { + return this.table.name; + } - public get description(): string | undefined { - return this._isDuplicate ? this.table.schemaName : undefined; - } + public get description(): string | undefined { + return this._isDuplicate ? this.table.schemaName : undefined; + } - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('window'); - } + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("window"); + } - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - return this.table.columnNames.map(columnName => new PostgresColumnTreeItem(this, columnName)); - } - - public async deleteTreeItemImpl(): Promise { - await runPostgresQuery(this.parent.clientConfig, `Drop Table ${this.table.schemaName}.${wrapArgInQuotes(this.table.name)};`); - } + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + return this.table.columnNames.map( + (columnName) => new PostgresColumnTreeItem(this, columnName) + ); + } + public async deleteTreeItemImpl(): Promise { + await runPostgresQuery( + this.parent.clientConfig, + `Drop Table ${this.table.schemaName}.${wrapArgInQuotes( + this.table.name + )};` + ); + } } diff --git a/Source/postgres/tree/PostgresTablesTreeItem.ts b/Source/postgres/tree/PostgresTablesTreeItem.ts index c18c065db..4c15ef812 100644 --- a/Source/postgres/tree/PostgresTablesTreeItem.ts +++ b/Source/postgres/tree/PostgresTablesTreeItem.ts @@ -5,47 +5,54 @@ import { TreeItemIconPath } from "@microsoft/vscode-azext-utils"; import { ClientConfig } from "pg"; -import { ThemeIcon } from 'vscode'; +import { ThemeIcon } from "vscode"; import { getTables, IPostgresTable } from "../getTables"; import { PostgresDatabaseTreeItem } from "./PostgresDatabaseTreeItem"; import { PostgresResourcesTreeItemBase } from "./PostgresResourcesTreeItemBase"; import { PostgresTableTreeItem } from "./PostgresTableTreeItem"; export class PostgresTablesTreeItem extends PostgresResourcesTreeItemBase { - public static contextValue: string = "postgresTables"; - public readonly contextValue: string = PostgresTablesTreeItem.contextValue; - public readonly childTypeLabel: string = "Table"; - public readonly label: string = 'Tables'; - public suppressMaskLabel = true; - - constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { - super(parent); - this.clientConfig = clientConfig; - } - - public get iconPath(): TreeItemIconPath { - return new ThemeIcon('window'); - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - - const tables: IPostgresTable[] = await getTables(this.clientConfig); - this.resourcesAndSchemas = {}; - for (const table of tables) { - this.addResourcesAndSchemasEntry(table.name.trim(), table.schemaName); - } - return tables.map(table => new PostgresTableTreeItem( - this, - table, - this.isDuplicateResource(table.name.trim()) - )); - } - - public isAncestorOfImpl(contextValue: string): boolean { - return contextValue === PostgresTableTreeItem.contextValue; - } + public static contextValue: string = "postgresTables"; + public readonly contextValue: string = PostgresTablesTreeItem.contextValue; + public readonly childTypeLabel: string = "Table"; + public readonly label: string = "Tables"; + public suppressMaskLabel = true; + + constructor(parent: PostgresDatabaseTreeItem, clientConfig: ClientConfig) { + super(parent); + this.clientConfig = clientConfig; + } + + public get iconPath(): TreeItemIconPath { + return new ThemeIcon("window"); + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const tables: IPostgresTable[] = await getTables(this.clientConfig); + this.resourcesAndSchemas = {}; + for (const table of tables) { + this.addResourcesAndSchemasEntry( + table.name.trim(), + table.schemaName + ); + } + return tables.map( + (table) => + new PostgresTableTreeItem( + this, + table, + this.isDuplicateResource(table.name.trim()) + ) + ); + } + + public isAncestorOfImpl(contextValue: string): boolean { + return contextValue === PostgresTableTreeItem.contextValue; + } } diff --git a/Source/resolver/AppResolver.ts b/Source/resolver/AppResolver.ts index 0f75cdf29..7d20a4832 100644 --- a/Source/resolver/AppResolver.ts +++ b/Source/resolver/AppResolver.ts @@ -4,8 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { getResourceGroupFromId } from "@microsoft/vscode-azext-azureutils"; -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp, nonNullValue } from "@microsoft/vscode-azext-utils"; -import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, + ISubscriptionContext, + nonNullProp, + nonNullValue, +} from "@microsoft/vscode-azext-utils"; +import { + AppResource, + AppResourceResolver, +} from "@microsoft/vscode-azext-utils/hostapi"; import { tryGetExperience } from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; import { ext } from "../extensionVariables"; @@ -13,59 +24,111 @@ import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresAbstractServer } from "../postgres/abstract/models"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem"; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; +import { + createCosmosDBClient, + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../utils/azureClients"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; import { ResolvedDocDBAccountResource } from "./ResolvedDocDBAccountResource"; import { ResolvedMongoAccountResource } from "./ResolvedMongoAccountResource"; import { ResolvedPostgresServerResource } from "./ResolvedPostgresServerResource"; const resourceTypes = [ - 'microsoft.documentdb/databaseaccounts', - 'microsoft.dbforpostgresql/servers', - 'microsoft.dbforpostgresql/flexibleservers' + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers", ]; export class DatabaseResolver implements AppResourceResolver { - public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise { - return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => { - const subNode: AzExtParentTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(`/subscriptions/${subContext.subscriptionId}`, context); - try { - const resourceGroupName = getResourceGroupFromId(nonNullProp(resource, 'id')); - const name = nonNullProp(resource, 'name'); - let postgresServer: PostgresAbstractServer; - let dbChild: AzExtTreeItem; + public async resolveResource( + subContext: ISubscriptionContext, + resource: AppResource + ): Promise { + return await callWithTelemetryAndErrorHandling( + "resolveResource", + async (context: IActionContext) => { + const subNode: AzExtParentTreeItem | undefined = + await ext.rgApi.appResourceTree.findTreeItem( + `/subscriptions/${subContext.subscriptionId}`, + context + ); + try { + const resourceGroupName = getResourceGroupFromId( + nonNullProp(resource, "id") + ); + const name = nonNullProp(resource, "name"); + let postgresServer: PostgresAbstractServer; + let dbChild: AzExtTreeItem; - switch (resource.type.toLowerCase()) { - case resourceTypes[0]: - const client = await createCosmosDBClient({ ...context, ...subContext }); - const databaseAccount = await client.databaseAccounts.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initCosmosDBChild(client, databaseAccount, nonNullValue(subNode)); - const experience = tryGetExperience(databaseAccount); + switch (resource.type.toLowerCase()) { + case resourceTypes[0]: + const client = await createCosmosDBClient({ + ...context, + ...subContext, + }); + const databaseAccount = + await client.databaseAccounts.get( + resourceGroupName, + name + ); + dbChild = + await SubscriptionTreeItem.initCosmosDBChild( + client, + databaseAccount, + nonNullValue(subNode) + ); + const experience = + tryGetExperience(databaseAccount); - return experience?.api === 'MongoDB' ? - new ResolvedMongoAccountResource(dbChild as MongoAccountTreeItem, resource) : - new ResolvedDocDBAccountResource(dbChild as DocDBAccountTreeItem, resource); - case resourceTypes[1]: - case resourceTypes[2]: - const postgresClient = resource.type.toLowerCase() === resourceTypes[1] ? - await createPostgreSQLClient({ ...context, ...subContext }) : - await createPostgreSQLFlexibleClient({ ...context, ...subContext }); + return experience?.api === "MongoDB" + ? new ResolvedMongoAccountResource( + dbChild as MongoAccountTreeItem, + resource + ) + : new ResolvedDocDBAccountResource( + dbChild as DocDBAccountTreeItem, + resource + ); + case resourceTypes[1]: + case resourceTypes[2]: + const postgresClient = + resource.type.toLowerCase() === resourceTypes[1] + ? await createPostgreSQLClient({ + ...context, + ...subContext, + }) + : await createPostgreSQLFlexibleClient({ + ...context, + ...subContext, + }); - postgresServer = await postgresClient.servers.get(resourceGroupName, name); - dbChild = await SubscriptionTreeItem.initPostgresChild(postgresServer, nonNullValue(subNode)); + postgresServer = await postgresClient.servers.get( + resourceGroupName, + name + ); + dbChild = + await SubscriptionTreeItem.initPostgresChild( + postgresServer, + nonNullValue(subNode) + ); - return new ResolvedPostgresServerResource(dbChild as PostgresServerTreeItem, resource); - default: - return null; - } - } catch (e) { - console.error({ ...context, ...subContext }); - throw e; - } - }); - } + return new ResolvedPostgresServerResource( + dbChild as PostgresServerTreeItem, + resource + ); + default: + return null; + } + } catch (e) { + console.error({ ...context, ...subContext }); + throw e; + } + } + ); + } - public matchesResource(resource: AppResource): boolean { - return resourceTypes.includes(resource.type.toLowerCase()); - } + public matchesResource(resource: AppResource): boolean { + return resourceTypes.includes(resource.type.toLowerCase()); + } } diff --git a/Source/resolver/DatabaseWorkspaceProvider.ts b/Source/resolver/DatabaseWorkspaceProvider.ts index 14e50d643..d1f462a36 100644 --- a/Source/resolver/DatabaseWorkspaceProvider.ts +++ b/Source/resolver/DatabaseWorkspaceProvider.ts @@ -3,31 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + callWithTelemetryAndErrorHandling, + IActionContext, +} from "@microsoft/vscode-azext-utils"; import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi"; import { Disposable } from "vscode"; import { ext } from "../extensionVariables"; import { AttachedAccountsTreeItem } from "../tree/AttachedAccountsTreeItem"; - export class DatabaseWorkspaceProvider implements WorkspaceResourceProvider { - - public disposables: Disposable[] = []; - - constructor(parent: AzExtParentTreeItem) { - ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); - } - - public async provideResources(): Promise { - - return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (_context: IActionContext) => { - return [ext.attachedAccountsNode]; - }); - } - private _projectDisposables: Disposable[] = []; - - public dispose(): void { - Disposable.from(...this._projectDisposables).dispose(); - } + public disposables: Disposable[] = []; + + constructor(parent: AzExtParentTreeItem) { + ext.attachedAccountsNode = new AttachedAccountsTreeItem(parent); + } + + public async provideResources(): Promise< + AzExtTreeItem[] | null | undefined + > { + return await callWithTelemetryAndErrorHandling( + "AzureAccountTreeItemWithProjects.provideResources", + async (_context: IActionContext) => { + return [ext.attachedAccountsNode]; + } + ); + } + private _projectDisposables: Disposable[] = []; + + public dispose(): void { + Disposable.from(...this._projectDisposables).dispose(); + } } - diff --git a/Source/resolver/ResolvedDatabaseAccountResource.ts b/Source/resolver/ResolvedDatabaseAccountResource.ts index 0222dded7..41eda32be 100644 --- a/Source/resolver/ResolvedDatabaseAccountResource.ts +++ b/Source/resolver/ResolvedDatabaseAccountResource.ts @@ -3,55 +3,78 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AzExtTreeItem, + IActionContext, + ICreateChildImplContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; -export class ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public id: string; - public contextValuesToAdd: string[] = []; - public description: string | undefined; - - // private _databaseTreeItem: AzExtParentTreeItem; - iconPath: TreeItemIconPath | undefined; - label: string; - - readonly childTypeLabel: string; - - loadMoreChildrenImpl?(clearCache: boolean, context: IActionContext): Promise; - createChildImpl?(context: ICreateChildImplContext): Promise; - hasMoreChildrenImpl?(): boolean; - compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; - - pickTreeItemImpl?(expectedContextValues: (string | RegExp)[], context: IActionContext): AzExtTreeItem | undefined | Promise; - deleteTreeItemImpl?(context: IActionContext): Promise; - refreshImpl?(context: IActionContext): Promise; - isAncestorOfImpl?(contextValue: string): boolean; - - connectionString: string; - maskedValuestoAdd: string[] = []; - - public constructor(ti: DocDBAccountTreeItemBase | MongoAccountTreeItem | PostgresServerTreeItem, resource: AppResource) { - this.id = ti.id ?? resource.id; - // PostgresServerTreeItem require on a property on the server so wait to do this - this.description = ti instanceof PostgresServerTreeItem ? undefined : ti.description; - this.iconPath = ti.iconPath; - this.label = ti.label; - this.childTypeLabel = ti.childTypeLabel; - - this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; - this.createChildImpl = ti.createChildImpl; - this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; - this.compareChildrenImpl = ti.compareChildrenImpl; - - this.pickTreeItemImpl = ti.pickTreeItemImpl; - this.deleteTreeItemImpl = ti.deleteTreeItemImpl; - this.refreshImpl = ti.refreshImpl; - this.isAncestorOfImpl = ti.isAncestorOfImpl; - - this.contextValuesToAdd.push(ti.contextValue) - this.maskedValuestoAdd.push(...ti.valuesToMask); - } +export class ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public id: string; + public contextValuesToAdd: string[] = []; + public description: string | undefined; + + // private _databaseTreeItem: AzExtParentTreeItem; + iconPath: TreeItemIconPath | undefined; + label: string; + + readonly childTypeLabel: string; + + loadMoreChildrenImpl?( + clearCache: boolean, + context: IActionContext + ): Promise; + createChildImpl?(context: ICreateChildImplContext): Promise; + hasMoreChildrenImpl?(): boolean; + compareChildrenImpl?(item1: AzExtTreeItem, item2: AzExtTreeItem): number; + + pickTreeItemImpl?( + expectedContextValues: (string | RegExp)[], + context: IActionContext + ): AzExtTreeItem | undefined | Promise; + deleteTreeItemImpl?(context: IActionContext): Promise; + refreshImpl?(context: IActionContext): Promise; + isAncestorOfImpl?(contextValue: string): boolean; + + connectionString: string; + maskedValuestoAdd: string[] = []; + + public constructor( + ti: + | DocDBAccountTreeItemBase + | MongoAccountTreeItem + | PostgresServerTreeItem, + resource: AppResource + ) { + this.id = ti.id ?? resource.id; + // PostgresServerTreeItem require on a property on the server so wait to do this + this.description = + ti instanceof PostgresServerTreeItem ? undefined : ti.description; + this.iconPath = ti.iconPath; + this.label = ti.label; + this.childTypeLabel = ti.childTypeLabel; + + this.loadMoreChildrenImpl = ti.loadMoreChildrenImpl; + this.createChildImpl = ti.createChildImpl; + this.hasMoreChildrenImpl = ti.hasMoreChildrenImpl; + this.compareChildrenImpl = ti.compareChildrenImpl; + + this.pickTreeItemImpl = ti.pickTreeItemImpl; + this.deleteTreeItemImpl = ti.deleteTreeItemImpl; + this.refreshImpl = ti.refreshImpl; + this.isAncestorOfImpl = ti.isAncestorOfImpl; + + this.contextValuesToAdd.push(ti.contextValue); + this.maskedValuestoAdd.push(...ti.valuesToMask); + } } diff --git a/Source/resolver/ResolvedDocDBAccountResource.ts b/Source/resolver/ResolvedDocDBAccountResource.ts index cf1bfc4bc..02f17f6e3 100644 --- a/Source/resolver/ResolvedDocDBAccountResource.ts +++ b/Source/resolver/ResolvedDocDBAccountResource.ts @@ -1,32 +1,45 @@ - - /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + CosmosClient, + DatabaseDefinition, + FeedOptions, + QueryIterator, + Resource, +} from "@azure/cosmos"; import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; import { IDocDBTreeRoot } from "../docdb/tree/IDocDBTreeRoot"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedDocDBAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public root: IDocDBTreeRoot; - - initChild: (resource: Resource) => AzExtTreeItem; - isServerless?: boolean; - getIterator?: (client: CosmosClient, feedOptions: FeedOptions) => QueryIterator - - public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { - super(ti, resource); - - this.connectionString = ti.connectionString; - this.root = ti.root; - - this.isServerless = ti.isServerless - this.getIterator = ti.getIterator; - this.initChild = ti.initChild; - } +export class ResolvedDocDBAccountResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public root: IDocDBTreeRoot; + + initChild: (resource: Resource) => AzExtTreeItem; + isServerless?: boolean; + getIterator?: ( + client: CosmosClient, + feedOptions: FeedOptions + ) => QueryIterator; + + public constructor(ti: DocDBAccountTreeItemBase, resource: AppResource) { + super(ti, resource); + + this.connectionString = ti.connectionString; + this.root = ti.root; + + this.isServerless = ti.isServerless; + this.getIterator = ti.getIterator; + this.initChild = ti.initChild; + } } diff --git a/Source/resolver/ResolvedMongoAccountResource.ts b/Source/resolver/ResolvedMongoAccountResource.ts index 4f45486ef..80636b5e5 100644 --- a/Source/resolver/ResolvedMongoAccountResource.ts +++ b/Source/resolver/ResolvedMongoAccountResource.ts @@ -3,18 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { IMongoTreeRoot } from "../mongo/tree/IMongoTreeRoot"; import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedMongoAccountResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - root: IMongoTreeRoot; +export class ResolvedMongoAccountResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + root: IMongoTreeRoot; - public constructor(ti: MongoAccountTreeItem, resource: AppResource) { - super(ti, resource); + public constructor(ti: MongoAccountTreeItem, resource: AppResource) { + super(ti, resource); - this.connectionString = ti.connectionString; - this.root = ti.root; - } + this.connectionString = ti.connectionString; + this.root = ti.root; + } } diff --git a/Source/resolver/ResolvedPostgresServerResource.ts b/Source/resolver/ResolvedPostgresServerResource.ts index a1e35acf3..76007eac0 100644 --- a/Source/resolver/ResolvedPostgresServerResource.ts +++ b/Source/resolver/ResolvedPostgresServerResource.ts @@ -4,45 +4,54 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils"; -import { AppResource, ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi"; +import { + AppResource, + ResolvedAppResourceBase, +} from "@microsoft/vscode-azext-utils/hostapi"; import { ClientConfig } from "pg"; import { PostgresServerType } from "../postgres/abstract/models"; import { ParsedPostgresConnectionString } from "../postgres/postgresConnectionStrings"; import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { ResolvedDatabaseAccountResource } from "./ResolvedDatabaseAccountResource"; -export class ResolvedPostgresServerResource extends ResolvedDatabaseAccountResource implements ResolvedAppResourceBase { - public readonly serverType?: PostgresServerType; - - public resourceGroup: string | undefined; - public azureName: string | undefined; - public partialConnectionString: ParsedPostgresConnectionString; - - public azureId: string | undefined; - public serverVersion: string | undefined; - - setCredentials: (username: string, password: string) => void; - supportsStoredProcedures: (clientConfig: ClientConfig) => Promise - deletePostgresCredentials: () => Promise - getFullConnectionString: () => Promise - validateDatabaseName: (name: string, getChildrenTask: Promise) => Promise - isFirewallRuleSet: (context: IActionContext) => Promise - - public constructor(ti: PostgresServerTreeItem, resource: AppResource) { - super(ti, resource); - this.serverType = ti.serverType; - this.description = ti.description; - this.resourceGroup = ti.resourceGroup; - this.azureName = ti.azureName; - this.partialConnectionString = ti.partialConnectionString; - - this.azureId = ti.azureId; - this.serverVersion = ti.serverVersion; - - this.setCredentials = ti.setCredentials; - this.supportsStoredProcedures = ti.supportsStoredProcedures; - this.deletePostgresCredentials = ti.deletePostgresCredentials; - this.getFullConnectionString = ti.getFullConnectionString; - this.isFirewallRuleSet = ti.isFirewallRuleSet; - } +export class ResolvedPostgresServerResource + extends ResolvedDatabaseAccountResource + implements ResolvedAppResourceBase +{ + public readonly serverType?: PostgresServerType; + + public resourceGroup: string | undefined; + public azureName: string | undefined; + public partialConnectionString: ParsedPostgresConnectionString; + + public azureId: string | undefined; + public serverVersion: string | undefined; + + setCredentials: (username: string, password: string) => void; + supportsStoredProcedures: (clientConfig: ClientConfig) => Promise; + deletePostgresCredentials: () => Promise; + getFullConnectionString: () => Promise; + validateDatabaseName: ( + name: string, + getChildrenTask: Promise + ) => Promise; + isFirewallRuleSet: (context: IActionContext) => Promise; + + public constructor(ti: PostgresServerTreeItem, resource: AppResource) { + super(ti, resource); + this.serverType = ti.serverType; + this.description = ti.description; + this.resourceGroup = ti.resourceGroup; + this.azureName = ti.azureName; + this.partialConnectionString = ti.partialConnectionString; + + this.azureId = ti.azureId; + this.serverVersion = ti.serverVersion; + + this.setCredentials = ti.setCredentials; + this.supportsStoredProcedures = ti.supportsStoredProcedures; + this.deletePostgresCredentials = ti.deletePostgresCredentials; + this.getFullConnectionString = ti.getFullConnectionString; + this.isFirewallRuleSet = ti.isFirewallRuleSet; + } } diff --git a/Source/table/tree/TableAccountTreeItem.ts b/Source/table/tree/TableAccountTreeItem.ts index 0d3b86e38..fb2616da9 100644 --- a/Source/table/tree/TableAccountTreeItem.ts +++ b/Source/table/tree/TableAccountTreeItem.ts @@ -4,36 +4,40 @@ *--------------------------------------------------------------------------------------------*/ import { AzExtTreeItem, GenericTreeItem } from "@microsoft/vscode-azext-utils"; -import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount'; +import { deleteCosmosDBAccount } from "../../commands/deleteDatabaseAccount/deleteCosmosDBAccount"; import { IDeleteWizardContext } from "../../commands/deleteDatabaseAccount/IDeleteWizardContext"; import { DocDBAccountTreeItemBase } from "../../docdb/tree/DocDBAccountTreeItemBase"; export class TableAccountTreeItem extends DocDBAccountTreeItemBase { - public static contextValue: string = "cosmosDBTableAccount"; - public contextValue: string = TableAccountTreeItem.contextValue; + public static contextValue: string = "cosmosDBTableAccount"; + public contextValue: string = TableAccountTreeItem.contextValue; - public hasMoreChildrenImpl(): boolean { - return false; - } + public hasMoreChildrenImpl(): boolean { + return false; + } - public initChild(): AzExtTreeItem { - throw new Error('Table Accounts are not supported yet.'); - } + public initChild(): AzExtTreeItem { + throw new Error("Table Accounts are not supported yet."); + } - public async loadMoreChildrenImpl(_clearCache: boolean): Promise { - const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { - contextValue: 'tableNotSupported', - label: 'Table Accounts are not supported yet.' - }); - tableNotFoundTreeItem.suppressMaskLabel = true; - return [tableNotFoundTreeItem]; - } + public async loadMoreChildrenImpl( + _clearCache: boolean + ): Promise { + const tableNotFoundTreeItem: AzExtTreeItem = new GenericTreeItem(this, { + contextValue: "tableNotSupported", + label: "Table Accounts are not supported yet.", + }); + tableNotFoundTreeItem.suppressMaskLabel = true; + return [tableNotFoundTreeItem]; + } - public async deleteTreeItemImpl(context: IDeleteWizardContext): Promise { - await deleteCosmosDBAccount(context, this); - } + public async deleteTreeItemImpl( + context: IDeleteWizardContext + ): Promise { + await deleteCosmosDBAccount(context, this); + } - public isAncestorOfImpl(): boolean { - return false; - } + public isAncestorOfImpl(): boolean { + return false; + } } diff --git a/Source/tree/AttachedAccountsTreeItem.ts b/Source/tree/AttachedAccountsTreeItem.ts index d854e506f..47aa8bdc3 100644 --- a/Source/tree/AttachedAccountsTreeItem.ts +++ b/Source/tree/AttachedAccountsTreeItem.ts @@ -3,418 +3,605 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { appendExtensionUserAgent, AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, ISubscriptionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils'; -import { MongoClient } from 'mongodb'; -import * as vscode from 'vscode'; -import { API, getExperienceFromApi, getExperienceQuickPick, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { removeTreeItemFromCache } from '../commands/api/apiCache'; -import { emulatorPassword, isWindows } from '../constants'; -import { parseDocDBConnectionString } from '../docdb/docDBConnectionStrings'; -import { DocDBAccountTreeItem } from '../docdb/tree/DocDBAccountTreeItem'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { GraphAccountTreeItem } from '../graph/tree/GraphAccountTreeItem'; -import { connectToMongoClient } from '../mongo/connectToMongoClient'; -import { parseMongoConnectionString } from '../mongo/mongoConnectionStrings'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; -import { TableAccountTreeItem } from '../table/tree/TableAccountTreeItem'; -import { getSecretStorageKey } from '../utils/getSecretStorageKey'; -import { localize } from '../utils/localize'; -import { nonNullProp, nonNullValue } from '../utils/nonNull'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; +import { + appendExtensionUserAgent, + AzExtParentTreeItem, + AzExtTreeItem, + GenericTreeItem, + IActionContext, + ISubscriptionContext, + TreeItemIconPath, +} from "@microsoft/vscode-azext-utils"; +import { MongoClient } from "mongodb"; +import * as vscode from "vscode"; +import { + API, + getExperienceFromApi, + getExperienceQuickPick, + getExperienceQuickPicks, +} from "../AzureDBExperiences"; +import { removeTreeItemFromCache } from "../commands/api/apiCache"; +import { emulatorPassword, isWindows } from "../constants"; +import { parseDocDBConnectionString } from "../docdb/docDBConnectionStrings"; +import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; +import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../extensionVariables"; +import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; +import { connectToMongoClient } from "../mongo/connectToMongoClient"; +import { parseMongoConnectionString } from "../mongo/mongoConnectionStrings"; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { parsePostgresConnectionString } from "../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; +import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; +import { getSecretStorageKey } from "../utils/getSecretStorageKey"; +import { localize } from "../utils/localize"; +import { nonNullProp, nonNullValue } from "../utils/nonNull"; +import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; interface IPersistedAccount { - id: string; - // defaultExperience is not the same as API but we can't change the name due to backwards compatibility - defaultExperience: API; - isEmulator: boolean | undefined; + id: string; + // defaultExperience is not the same as API but we can't change the name due to backwards compatibility + defaultExperience: API; + isEmulator: boolean | undefined; } -export const AttachedAccountSuffix: string = 'Attached'; -export const MONGO_CONNECTION_EXPECTED: string = 'Connection string must start with "mongodb://" or "mongodb+srv://"'; +export const AttachedAccountSuffix: string = "Attached"; +export const MONGO_CONNECTION_EXPECTED: string = + 'Connection string must start with "mongodb://" or "mongodb+srv://"'; -const localMongoConnectionString: string = 'mongodb://127.0.0.1:27017'; +const localMongoConnectionString: string = "mongodb://127.0.0.1:27017"; export class AttachedAccountsTreeItem extends AzExtParentTreeItem { - public static contextValue: string = 'cosmosDBAttachedAccounts' + (isWindows ? 'WithEmulator' : 'WithoutEmulator'); - public readonly contextValue: string = AttachedAccountsTreeItem.contextValue; - public readonly label: string = 'Attached Database Accounts'; - public childTypeLabel: string = 'Account'; - public suppressMaskLabel = true; - - private readonly _serviceName: string = "ms-azuretools.vscode-cosmosdb.connectionStrings"; - private _attachedAccounts: AzExtTreeItem[] | undefined; - - private _root: ISubscriptionContext; - private _loadPersistedAccountsTask: Promise; - - constructor(parent: AzExtParentTreeItem) { - super(parent); - this._root = new AttachedAccountRoot(); - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - this.id = 'cosmosDBAttachedAccounts'; - } - - public get root(): ISubscriptionContext { - return this._root; - } - - public get iconPath(): TreeItemIconPath { - return new vscode.ThemeIcon('plug'); - } - - public static validateMongoConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^mongodb(\+srv)?:\/\//)) { - return undefined; - } - - return MONGO_CONNECTION_EXPECTED; - } - - public static validatePostgresConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - if (value && value.match(/^postgres:\/\//)) { - return undefined; - } - - return localize('invalidPostgresConnectionString', 'Connection string must start with "postgres://"'); - } - - private static validateDocDBConnectionString(value: string): string | undefined { - value = value ? value.trim() : ''; - - try { - parseDocDBConnectionString(value); - return undefined; - } catch (error) { - return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; - } - } - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(clearCache: boolean): Promise { - if (clearCache) { - this._attachedAccounts = undefined; - this._loadPersistedAccountsTask = this.loadPersistedAccounts(); - } - - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.length > 0) { - return attachedAccounts; - } else { - const attachDatabaseAccount = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachDatabaseAccount', - label: 'Attach Database Account...', - commandId: 'cosmosDB.attachDatabaseAccount', - includeInTreeItemPicker: true - }); - const attachEmulator = new GenericTreeItem(this, { - contextValue: 'cosmosDBAttachEmulator', - label: 'Attach Emulator...', - commandId: 'cosmosDB.attachEmulator', - includeInTreeItemPicker: true - }); - return isWindows ? [attachDatabaseAccount, attachEmulator] : - [attachDatabaseAccount]; - } - } - - public isAncestorOfImpl(contextValue: string): boolean { - switch (contextValue) { - // We have to make sure the Attached Accounts node is not shown for commands like - // 'Open in Portal', which only work for the non-attached version - case GraphAccountTreeItem.contextValue: - case MongoAccountTreeItem.contextValue: - case DocDBAccountTreeItem.contextValue: - case TableAccountTreeItem.contextValue: - case PostgresServerTreeItem.contextValue: - case SubscriptionTreeItem.contextValue: - return false; - default: - return true; - } - } - - public async attachNewAccount(context: IActionContext): Promise { - const defaultExperiencePick = await context.ui.showQuickPick(getExperienceQuickPicks(true), { placeHolder: "Select a Database type...", stepName: 'attachNewAccount' }); - const defaultExperience = defaultExperiencePick.data; - let placeholder: string; - let defaultValue: string | undefined; - let validateInput: (value: string) => string | undefined | null; - if (defaultExperience.api === API.MongoDB) { - placeholder = 'mongodb://host:port'; - if (await this.canConnectToLocalMongoDB()) { - defaultValue = placeholder = localMongoConnectionString; - } - validateInput = AttachedAccountsTreeItem.validateMongoConnectionString; - } else if (defaultExperience.api === API.PostgresSingle || defaultExperience.api === API.PostgresFlexible) { - placeholder = localize('attachedPostgresPlaceholder', '"postgres://username:password@host" or "postgres://username:password@host/database"'); - validateInput = AttachedAccountsTreeItem.validatePostgresConnectionString; - } else { - placeholder = 'AccountEndpoint=...;AccountKey=...'; - validateInput = AttachedAccountsTreeItem.validateDocDBConnectionString; - } - - const connectionString = (await context.ui.showInputBox({ - placeHolder: placeholder, - prompt: 'Enter the connection string for your database account', - stepName: 'attachNewAccountConnectionString', - validateInput: validateInput, - value: defaultValue - })).trim(); - - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api); - await this.attachAccount(context, treeItem, connectionString); - } - - public async attachConnectionString(context: IActionContext, connectionString: string, api: API.MongoDB | API.Core | API.PostgresSingle): Promise { - const treeItem = await this.createTreeItem(connectionString, api); - await this.attachAccount(context, treeItem, connectionString); - await this.refresh(context); - return treeItem; - } - - public async attachEmulator(context: IActionContext): Promise { - let connectionString: string; - const defaultExperiencePick = await context.ui.showQuickPick( - [ - getExperienceQuickPick(API.MongoDB), - getExperienceQuickPick(API.Core) - ], - { - placeHolder: "Select a Database Account API...", - stepName: 'attachEmulator' - }); - const defaultExperience = defaultExperiencePick.data; - let port: number | undefined; - if (defaultExperience.api === API.MongoDB) { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.mongoPort"); - } else { - port = vscode.workspace.getConfiguration().get("cosmosDB.emulator.port"); - } - if (port) { - if (defaultExperience.api === API.MongoDB) { - // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions - connectionString = `mongodb://localhost:${encodeURIComponent(emulatorPassword)}@localhost:${port}/?ssl=true`; - } else { - connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; - } - const label = `${defaultExperience.shortName} Emulator`; - const treeItem: AzExtTreeItem = await this.createTreeItem(connectionString, defaultExperience.api, label); - if (treeItem instanceof DocDBAccountTreeItem || treeItem instanceof GraphAccountTreeItem || treeItem instanceof TableAccountTreeItem || treeItem instanceof MongoAccountTreeItem) { - // CONSIDER: Why isn't this passed in to createTreeItem above? - treeItem.root.isEmulator = true; - } - await this.attachAccount(context, treeItem, connectionString); - } - } - - public async detach(node: AzExtTreeItem): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - const index = attachedAccounts.findIndex((account) => account.fullId === node.fullId); - if (index !== -1) { - attachedAccounts.splice(index, 1); - await ext.secretStorage.delete(getSecretStorageKey(this._serviceName, nonNullProp(node, 'id'))); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility - await this.persistIds(attachedAccounts); - - if (node instanceof MongoAccountTreeItem) { - const parsedCS = await parseMongoConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof DocDBAccountTreeItemBase) { - const parsedCS = parseDocDBConnectionString(node.connectionString); - removeTreeItemFromCache(parsedCS); - } else if (node instanceof PostgresServerTreeItem) { - const parsedCS = node.partialConnectionString; - removeTreeItemFromCache(parsedCS); - } - } - } - - private async getAttachedAccounts(): Promise { - if (!this._attachedAccounts) { - try { - this._attachedAccounts = await this._loadPersistedAccountsTask; - } catch { - this._attachedAccounts = []; - throw new Error('Failed to load persisted Database Accounts. Reattach the accounts manually.'); - } - } - - return this._attachedAccounts; - } - - private async canConnectToLocalMongoDB(): Promise { - async function timeout(): Promise { - await delay(1000); - return false; - } - async function connect(): Promise { - try { - const db: MongoClient = await connectToMongoClient(localMongoConnectionString, appendExtensionUserAgent()); - void db.close(); - return true; - } catch { - return false; - } - } - return await Promise.race([timeout(), connect()]); - } - - private async attachAccount(context: IActionContext, treeItem: AzExtTreeItem, connectionString: string): Promise { - const attachedAccounts: AzExtTreeItem[] = await this.getAttachedAccounts(); - - if (attachedAccounts.find(s => s.id === treeItem.id)) { - void context.ui.showWarningMessage(`Database Account '${treeItem.id}' is already attached.`, { stepName: 'attachAccount' }); - } else { - attachedAccounts.push(treeItem); - await ext.secretStorage.store(getSecretStorageKey(this._serviceName, nonNullProp(treeItem, 'id')), connectionString); - await this.persistIds(attachedAccounts); - } - } - - private async loadPersistedAccounts(): Promise { - const persistedAccounts: AzExtTreeItem[] = []; - const value: string | undefined = ext.context.globalState.get(this._serviceName); - if (value) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const accounts: (string | IPersistedAccount)[] = JSON.parse(value); - await Promise.all(accounts.map(async account => { - let id: string; - let label: string; - let api: API; - let isEmulator: boolean | undefined; - if (typeof (account) === 'string') { - // Default to Mongo if the value is a string for the sake of backwards compatibility - // (Mongo was originally the only account type that could be attached) - id = account; - api = API.MongoDB; - label = `${account} (${getExperienceFromApi(api).shortName})`; - isEmulator = false; - } else { - id = (account).id; - api = (account).defaultExperience; - isEmulator = (account).isEmulator; - label = isEmulator ? `${getExperienceFromApi(api).shortName} Emulator` : `${id} (${getExperienceFromApi(api).shortName})`; - } - // TODO: keytar: migration plan? - const connectionString: string = nonNullValue(await ext.secretStorage.get(getSecretStorageKey(this._serviceName, id)), 'connectionString'); - persistedAccounts.push(await this.createTreeItem(connectionString, api, label, id, isEmulator)); - })); - } - - return persistedAccounts; - } - - private async createTreeItem(connectionString: string, api: API, label?: string, id?: string, isEmulator?: boolean): Promise { - let treeItem: AzExtTreeItem; - if (api === API.MongoDB) { - if (id === undefined) { - const parsedCS = await parseMongoConnectionString(connectionString); - id = parsedCS.fullId; - } - - label = label || `${id} (${getExperienceFromApi(api).shortName})`; - treeItem = new MongoAccountTreeItem(this, id, label, connectionString, isEmulator); - } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { - const parsedPostgresConnString = parsePostgresConnectionString(connectionString); - treeItem = new PostgresServerTreeItem(this, parsedPostgresConnString); - } else { - const parsedCS = parseDocDBConnectionString(connectionString); - - label = label || `${parsedCS.accountId} (${getExperienceFromApi(api).shortName})`; - switch (api) { - case API.Table: - treeItem = new TableAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - case API.Graph: - treeItem = new GraphAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, undefined, parsedCS.masterKey, isEmulator); - break; - case API.Core: - treeItem = new DocDBAccountTreeItem(this, parsedCS.accountId, label, parsedCS.documentEndpoint, parsedCS.masterKey, isEmulator); - break; - default: - throw new Error(`Unexpected defaultExperience "${api}".`); - } - } - - treeItem.contextValue += AttachedAccountSuffix; - return treeItem; - } - - private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { - const value: IPersistedAccount[] = attachedAccounts.map((node: AzExtTreeItem) => { - let api: API; - let isEmulator: boolean | undefined; - if (node instanceof MongoAccountTreeItem || node instanceof DocDBAccountTreeItem || node instanceof GraphAccountTreeItem || node instanceof TableAccountTreeItem) { - isEmulator = node.root.isEmulator; - } - if (node instanceof MongoAccountTreeItem) { - api = API.MongoDB; - } else if (node instanceof GraphAccountTreeItem) { - api = API.Graph; - } else if (node instanceof TableAccountTreeItem) { - api = API.Table; - } else if (node instanceof DocDBAccountTreeItem) { - api = API.Core; - } else if (node instanceof PostgresServerTreeItem) { - api = API.PostgresSingle; - } else { - throw new Error(`Unexpected account node "${node.constructor.name}".`); - } - return { id: nonNullProp(node, 'id'), defaultExperience: api, isEmulator: isEmulator }; - }); - await ext.context.globalState.update(this._serviceName, JSON.stringify(value)); - } + public static contextValue: string = + "cosmosDBAttachedAccounts" + + (isWindows ? "WithEmulator" : "WithoutEmulator"); + public readonly contextValue: string = + AttachedAccountsTreeItem.contextValue; + public readonly label: string = "Attached Database Accounts"; + public childTypeLabel: string = "Account"; + public suppressMaskLabel = true; + + private readonly _serviceName: string = + "ms-azuretools.vscode-cosmosdb.connectionStrings"; + private _attachedAccounts: AzExtTreeItem[] | undefined; + + private _root: ISubscriptionContext; + private _loadPersistedAccountsTask: Promise; + + constructor(parent: AzExtParentTreeItem) { + super(parent); + this._root = new AttachedAccountRoot(); + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + this.id = "cosmosDBAttachedAccounts"; + } + + public get root(): ISubscriptionContext { + return this._root; + } + + public get iconPath(): TreeItemIconPath { + return new vscode.ThemeIcon("plug"); + } + + public static validateMongoConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + if (value && value.match(/^mongodb(\+srv)?:\/\//)) { + return undefined; + } + + return MONGO_CONNECTION_EXPECTED; + } + + public static validatePostgresConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + if (value && value.match(/^postgres:\/\//)) { + return undefined; + } + + return localize( + "invalidPostgresConnectionString", + 'Connection string must start with "postgres://"' + ); + } + + private static validateDocDBConnectionString( + value: string + ): string | undefined { + value = value ? value.trim() : ""; + + try { + parseDocDBConnectionString(value); + return undefined; + } catch (error) { + return 'Connection string must be of the form "AccountEndpoint=...;AccountKey=..."'; + } + } + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + clearCache: boolean + ): Promise { + if (clearCache) { + this._attachedAccounts = undefined; + this._loadPersistedAccountsTask = this.loadPersistedAccounts(); + } + + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + if (attachedAccounts.length > 0) { + return attachedAccounts; + } else { + const attachDatabaseAccount = new GenericTreeItem(this, { + contextValue: "cosmosDBAttachDatabaseAccount", + label: "Attach Database Account...", + commandId: "cosmosDB.attachDatabaseAccount", + includeInTreeItemPicker: true, + }); + const attachEmulator = new GenericTreeItem(this, { + contextValue: "cosmosDBAttachEmulator", + label: "Attach Emulator...", + commandId: "cosmosDB.attachEmulator", + includeInTreeItemPicker: true, + }); + return isWindows + ? [attachDatabaseAccount, attachEmulator] + : [attachDatabaseAccount]; + } + } + + public isAncestorOfImpl(contextValue: string): boolean { + switch (contextValue) { + // We have to make sure the Attached Accounts node is not shown for commands like + // 'Open in Portal', which only work for the non-attached version + case GraphAccountTreeItem.contextValue: + case MongoAccountTreeItem.contextValue: + case DocDBAccountTreeItem.contextValue: + case TableAccountTreeItem.contextValue: + case PostgresServerTreeItem.contextValue: + case SubscriptionTreeItem.contextValue: + return false; + default: + return true; + } + } + + public async attachNewAccount(context: IActionContext): Promise { + const defaultExperiencePick = await context.ui.showQuickPick( + getExperienceQuickPicks(true), + { + placeHolder: "Select a Database type...", + stepName: "attachNewAccount", + } + ); + const defaultExperience = defaultExperiencePick.data; + let placeholder: string; + let defaultValue: string | undefined; + let validateInput: (value: string) => string | undefined | null; + if (defaultExperience.api === API.MongoDB) { + placeholder = "mongodb://host:port"; + if (await this.canConnectToLocalMongoDB()) { + defaultValue = placeholder = localMongoConnectionString; + } + validateInput = + AttachedAccountsTreeItem.validateMongoConnectionString; + } else if ( + defaultExperience.api === API.PostgresSingle || + defaultExperience.api === API.PostgresFlexible + ) { + placeholder = localize( + "attachedPostgresPlaceholder", + '"postgres://username:password@host" or "postgres://username:password@host/database"' + ); + validateInput = + AttachedAccountsTreeItem.validatePostgresConnectionString; + } else { + placeholder = "AccountEndpoint=...;AccountKey=..."; + validateInput = + AttachedAccountsTreeItem.validateDocDBConnectionString; + } + + const connectionString = ( + await context.ui.showInputBox({ + placeHolder: placeholder, + prompt: "Enter the connection string for your database account", + stepName: "attachNewAccountConnectionString", + validateInput: validateInput, + value: defaultValue, + }) + ).trim(); + + const treeItem: AzExtTreeItem = await this.createTreeItem( + connectionString, + defaultExperience.api + ); + await this.attachAccount(context, treeItem, connectionString); + } + + public async attachConnectionString( + context: IActionContext, + connectionString: string, + api: API.MongoDB | API.Core | API.PostgresSingle + ): Promise< + MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem + > { + const treeItem = < + | MongoAccountTreeItem + | DocDBAccountTreeItemBase + | PostgresServerTreeItem + >await this.createTreeItem(connectionString, api); + await this.attachAccount(context, treeItem, connectionString); + await this.refresh(context); + return treeItem; + } + + public async attachEmulator(context: IActionContext): Promise { + let connectionString: string; + const defaultExperiencePick = await context.ui.showQuickPick( + [ + getExperienceQuickPick(API.MongoDB), + getExperienceQuickPick(API.Core), + ], + { + placeHolder: "Select a Database Account API...", + stepName: "attachEmulator", + } + ); + const defaultExperience = defaultExperiencePick.data; + let port: number | undefined; + if (defaultExperience.api === API.MongoDB) { + port = vscode.workspace + .getConfiguration() + .get("cosmosDB.emulator.mongoPort"); + } else { + port = vscode.workspace + .getConfiguration() + .get("cosmosDB.emulator.port"); + } + if (port) { + if (defaultExperience.api === API.MongoDB) { + // Mongo shell doesn't parse passwords with slashes, so we need to URI encode it. The '/' before the options is required by mongo conventions + connectionString = `mongodb://localhost:${encodeURIComponent( + emulatorPassword + )}@localhost:${port}/?ssl=true`; + } else { + connectionString = `AccountEndpoint=https://localhost:${port}/;AccountKey=${emulatorPassword};`; + } + const label = `${defaultExperience.shortName} Emulator`; + const treeItem: AzExtTreeItem = await this.createTreeItem( + connectionString, + defaultExperience.api, + label + ); + if ( + treeItem instanceof DocDBAccountTreeItem || + treeItem instanceof GraphAccountTreeItem || + treeItem instanceof TableAccountTreeItem || + treeItem instanceof MongoAccountTreeItem + ) { + // CONSIDER: Why isn't this passed in to createTreeItem above? + treeItem.root.isEmulator = true; + } + await this.attachAccount(context, treeItem, connectionString); + } + } + + public async detach(node: AzExtTreeItem): Promise { + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + const index = attachedAccounts.findIndex( + (account) => account.fullId === node.fullId + ); + if (index !== -1) { + attachedAccounts.splice(index, 1); + await ext.secretStorage.delete( + getSecretStorageKey(this._serviceName, nonNullProp(node, "id")) + ); // intentionally using 'id' instead of 'fullId' for the sake of backwards compatibility + await this.persistIds(attachedAccounts); + + if (node instanceof MongoAccountTreeItem) { + const parsedCS = await parseMongoConnectionString( + node.connectionString + ); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof DocDBAccountTreeItemBase) { + const parsedCS = parseDocDBConnectionString( + node.connectionString + ); + removeTreeItemFromCache(parsedCS); + } else if (node instanceof PostgresServerTreeItem) { + const parsedCS = node.partialConnectionString; + removeTreeItemFromCache(parsedCS); + } + } + } + + private async getAttachedAccounts(): Promise { + if (!this._attachedAccounts) { + try { + this._attachedAccounts = await this._loadPersistedAccountsTask; + } catch { + this._attachedAccounts = []; + throw new Error( + "Failed to load persisted Database Accounts. Reattach the accounts manually." + ); + } + } + + return this._attachedAccounts; + } + + private async canConnectToLocalMongoDB(): Promise { + async function timeout(): Promise { + await delay(1000); + return false; + } + async function connect(): Promise { + try { + const db: MongoClient = await connectToMongoClient( + localMongoConnectionString, + appendExtensionUserAgent() + ); + void db.close(); + return true; + } catch { + return false; + } + } + return await Promise.race([timeout(), connect()]); + } + + private async attachAccount( + context: IActionContext, + treeItem: AzExtTreeItem, + connectionString: string + ): Promise { + const attachedAccounts: AzExtTreeItem[] = + await this.getAttachedAccounts(); + + if (attachedAccounts.find((s) => s.id === treeItem.id)) { + void context.ui.showWarningMessage( + `Database Account '${treeItem.id}' is already attached.`, + { stepName: "attachAccount" } + ); + } else { + attachedAccounts.push(treeItem); + await ext.secretStorage.store( + getSecretStorageKey( + this._serviceName, + nonNullProp(treeItem, "id") + ), + connectionString + ); + await this.persistIds(attachedAccounts); + } + } + + private async loadPersistedAccounts(): Promise { + const persistedAccounts: AzExtTreeItem[] = []; + const value: string | undefined = ext.context.globalState.get( + this._serviceName + ); + if (value) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const accounts: (string | IPersistedAccount)[] = JSON.parse(value); + await Promise.all( + accounts.map(async (account) => { + let id: string; + let label: string; + let api: API; + let isEmulator: boolean | undefined; + if (typeof account === "string") { + // Default to Mongo if the value is a string for the sake of backwards compatibility + // (Mongo was originally the only account type that could be attached) + id = account; + api = API.MongoDB; + label = `${account} (${ + getExperienceFromApi(api).shortName + })`; + isEmulator = false; + } else { + id = (account).id; + api = (account).defaultExperience; + isEmulator = (account).isEmulator; + label = isEmulator + ? `${getExperienceFromApi(api).shortName} Emulator` + : `${id} (${getExperienceFromApi(api).shortName})`; + } + // TODO: keytar: migration plan? + const connectionString: string = nonNullValue( + await ext.secretStorage.get( + getSecretStorageKey(this._serviceName, id) + ), + "connectionString" + ); + persistedAccounts.push( + await this.createTreeItem( + connectionString, + api, + label, + id, + isEmulator + ) + ); + }) + ); + } + + return persistedAccounts; + } + + private async createTreeItem( + connectionString: string, + api: API, + label?: string, + id?: string, + isEmulator?: boolean + ): Promise { + let treeItem: AzExtTreeItem; + if (api === API.MongoDB) { + if (id === undefined) { + const parsedCS = + await parseMongoConnectionString(connectionString); + id = parsedCS.fullId; + } + + label = label || `${id} (${getExperienceFromApi(api).shortName})`; + treeItem = new MongoAccountTreeItem( + this, + id, + label, + connectionString, + isEmulator + ); + } else if (api === API.PostgresSingle || api === API.PostgresFlexible) { + const parsedPostgresConnString = + parsePostgresConnectionString(connectionString); + treeItem = new PostgresServerTreeItem( + this, + parsedPostgresConnString + ); + } else { + const parsedCS = parseDocDBConnectionString(connectionString); + + label = + label || + `${parsedCS.accountId} (${ + getExperienceFromApi(api).shortName + })`; + switch (api) { + case API.Table: + treeItem = new TableAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + parsedCS.masterKey, + isEmulator + ); + break; + case API.Graph: + treeItem = new GraphAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + undefined, + parsedCS.masterKey, + isEmulator + ); + break; + case API.Core: + treeItem = new DocDBAccountTreeItem( + this, + parsedCS.accountId, + label, + parsedCS.documentEndpoint, + parsedCS.masterKey, + isEmulator + ); + break; + default: + throw new Error(`Unexpected defaultExperience "${api}".`); + } + } + + treeItem.contextValue += AttachedAccountSuffix; + return treeItem; + } + + private async persistIds(attachedAccounts: AzExtTreeItem[]): Promise { + const value: IPersistedAccount[] = attachedAccounts.map( + (node: AzExtTreeItem) => { + let api: API; + let isEmulator: boolean | undefined; + if ( + node instanceof MongoAccountTreeItem || + node instanceof DocDBAccountTreeItem || + node instanceof GraphAccountTreeItem || + node instanceof TableAccountTreeItem + ) { + isEmulator = node.root.isEmulator; + } + if (node instanceof MongoAccountTreeItem) { + api = API.MongoDB; + } else if (node instanceof GraphAccountTreeItem) { + api = API.Graph; + } else if (node instanceof TableAccountTreeItem) { + api = API.Table; + } else if (node instanceof DocDBAccountTreeItem) { + api = API.Core; + } else if (node instanceof PostgresServerTreeItem) { + api = API.PostgresSingle; + } else { + throw new Error( + `Unexpected account node "${node.constructor.name}".` + ); + } + return { + id: nonNullProp(node, "id"), + defaultExperience: api, + isEmulator: isEmulator, + }; + } + ); + await ext.context.globalState.update( + this._serviceName, + JSON.stringify(value) + ); + } } class AttachedAccountRoot implements ISubscriptionContext { - private _error: Error = new Error('Cannot retrieve Azure subscription information for an attached account.'); + private _error: Error = new Error( + "Cannot retrieve Azure subscription information for an attached account." + ); - public get credentials(): never { - throw this._error; - } + public get credentials(): never { + throw this._error; + } - public get subscriptionDisplayName(): never { - throw this._error; - } + public get subscriptionDisplayName(): never { + throw this._error; + } - public get subscriptionId(): never { - throw this._error; - } + public get subscriptionId(): never { + throw this._error; + } - public get subscriptionPath(): never { - throw this._error; - } + public get subscriptionPath(): never { + throw this._error; + } - public get tenantId(): never { - throw this._error; - } + public get tenantId(): never { + throw this._error; + } - public get userId(): never { - throw this._error; - } + public get userId(): never { + throw this._error; + } - public get environment(): never { - throw this._error; - } + public get environment(): never { + throw this._error; + } - public get isCustomCloud(): never { - throw this._error; - } + public get isCustomCloud(): never { + throw this._error; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/tree/AzureAccountTreeItemWithAttached.ts b/Source/tree/AzureAccountTreeItemWithAttached.ts index 172cd598f..ce1cdb8fd 100644 --- a/Source/tree/AzureAccountTreeItemWithAttached.ts +++ b/Source/tree/AzureAccountTreeItemWithAttached.ts @@ -3,34 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureAccountTreeItemBase } from '@microsoft/vscode-azext-azureutils'; -import { AzExtTreeItem, IActionContext, ISubscriptionContext } from '@microsoft/vscode-azext-utils'; -import { ext } from '../extensionVariables'; -import { AttachedAccountsTreeItem } from './AttachedAccountsTreeItem'; -import { SubscriptionTreeItem } from './SubscriptionTreeItem'; +import { AzureAccountTreeItemBase } from "@microsoft/vscode-azext-azureutils"; +import { + AzExtTreeItem, + IActionContext, + ISubscriptionContext, +} from "@microsoft/vscode-azext-utils"; +import { ext } from "../extensionVariables"; +import { AttachedAccountsTreeItem } from "./AttachedAccountsTreeItem"; +import { SubscriptionTreeItem } from "./SubscriptionTreeItem"; export class AzureAccountTreeItemWithAttached extends AzureAccountTreeItemBase { - public constructor(testAccount?: {}) { - super(undefined, testAccount); - ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); - } + public constructor(testAccount?: {}) { + super(undefined, testAccount); + ext.attachedAccountsNode = new AttachedAccountsTreeItem(this); + } - public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem { - return new SubscriptionTreeItem(this, root); - } + public createSubscriptionTreeItem( + root: ISubscriptionContext + ): SubscriptionTreeItem { + return new SubscriptionTreeItem(this, root); + } - public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise { - const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context); - return children.concat(ext.attachedAccountsNode); - } + public async loadMoreChildrenImpl( + clearCache: boolean, + context: IActionContext + ): Promise { + const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl( + clearCache, + context + ); + return children.concat(ext.attachedAccountsNode); + } - public compareChildrenImpl(item1: AzExtTreeItem, item2: AzExtTreeItem): number { - if (item1 instanceof AttachedAccountsTreeItem) { - return 1; - } else if (item2 instanceof AttachedAccountsTreeItem) { - return -1; - } else { - return super.compareChildrenImpl(item1, item2); - } - } + public compareChildrenImpl( + item1: AzExtTreeItem, + item2: AzExtTreeItem + ): number { + if (item1 instanceof AttachedAccountsTreeItem) { + return 1; + } else if (item2 instanceof AttachedAccountsTreeItem) { + return -1; + } else { + return super.compareChildrenImpl(item1, item2); + } + } } diff --git a/Source/tree/AzureDBAPIStep.ts b/Source/tree/AzureDBAPIStep.ts index 8a11fdc95..a59ebfd48 100644 --- a/Source/tree/AzureDBAPIStep.ts +++ b/Source/tree/AzureDBAPIStep.ts @@ -3,74 +3,103 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep, AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from '@microsoft/vscode-azext-utils'; -import { API, Experience, getExperienceQuickPicks } from '../AzureDBExperiences'; -import { PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { PostgresServerConfirmPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep'; -import { PostgresServerCreateStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep'; -import { PostgresServerCredPWStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep'; -import { PostgresServerCredUserStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep'; -import { PostgresServerNameStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerNameStep'; -import { PostgresServerSetCredentialsStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep'; -import { PostgresServerSkuStep } from '../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep'; -import { localize } from '../utils/localize'; -import { CosmosDBAccountCapacityStep } from './CosmosDBAccountWizard/CosmosDBAccountCapacityStep'; -import { CosmosDBAccountCreateStep } from './CosmosDBAccountWizard/CosmosDBAccountCreateStep'; -import { CosmosDBAccountNameStep } from './CosmosDBAccountWizard/CosmosDBAccountNameStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; -import { IAzureDBWizardContext } from './IAzureDBWizardContext'; +import { VerifyProvidersStep } from "@microsoft/vscode-azext-azureutils"; +import { + AzureWizardExecuteStep, + AzureWizardPromptStep, + IAzureQuickPickItem, + IWizardOptions, +} from "@microsoft/vscode-azext-utils"; +import { + API, + Experience, + getExperienceQuickPicks, +} from "../AzureDBExperiences"; +import { PostgresServerType } from "../postgres/abstract/models"; +import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; +import { PostgresServerConfirmPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep"; +import { PostgresServerCreateStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCreateStep"; +import { PostgresServerCredPWStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep"; +import { PostgresServerCredUserStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep"; +import { PostgresServerNameStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerNameStep"; +import { PostgresServerSetCredentialsStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep"; +import { PostgresServerSkuStep } from "../postgres/commands/createPostgresServer/steps/PostgresServerSkuStep"; +import { localize } from "../utils/localize"; +import { CosmosDBAccountCapacityStep } from "./CosmosDBAccountWizard/CosmosDBAccountCapacityStep"; +import { CosmosDBAccountCreateStep } from "./CosmosDBAccountWizard/CosmosDBAccountCreateStep"; +import { CosmosDBAccountNameStep } from "./CosmosDBAccountWizard/CosmosDBAccountNameStep"; +import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; +import { IAzureDBWizardContext } from "./IAzureDBWizardContext"; -export class AzureDBAPIStep extends AzureWizardPromptStep { - public async prompt(context: IAzureDBWizardContext): Promise { - const picks: IAzureQuickPickItem[] = getExperienceQuickPicks(); +export class AzureDBAPIStep extends AzureWizardPromptStep< + IPostgresServerWizardContext | ICosmosDBWizardContext +> { + public async prompt(context: IAzureDBWizardContext): Promise { + const picks: IAzureQuickPickItem[] = + getExperienceQuickPicks(); - const result: IAzureQuickPickItem = await context.ui.showQuickPick(picks, { - placeHolder: localize('selectDBServerMsg', 'Select an Azure Database Server.') - }); + const result: IAzureQuickPickItem = + await context.ui.showQuickPick(picks, { + placeHolder: localize( + "selectDBServerMsg", + "Select an Azure Database Server." + ), + }); - context.defaultExperience = result.data; - } + context.defaultExperience = result.data; + } - public async getSubWizard(context: IAzureDBWizardContext): Promise> { - let promptSteps: AzureWizardPromptStep[]; - let executeSteps: AzureWizardExecuteStep[]; - if (context.defaultExperience?.api === API.PostgresSingle || context.defaultExperience?.api === API.PostgresFlexible) { - switch (context.defaultExperience?.api) { - case API.PostgresFlexible: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Flexible; - break; - case API.PostgresSingle: - (context as IPostgresServerWizardContext).serverType = PostgresServerType.Single; - break; - } - promptSteps = [ - new PostgresServerNameStep(), - new PostgresServerSkuStep(), - new PostgresServerCredUserStep(), - new PostgresServerCredPWStep(), - new PostgresServerConfirmPWStep(), - ]; - executeSteps = [ - new PostgresServerCreateStep(), - new PostgresServerSetCredentialsStep(), - new VerifyProvidersStep(['Microsoft.DBforPostgreSQL']) - ]; - } else { - promptSteps = [ - new CosmosDBAccountNameStep(), - new CosmosDBAccountCapacityStep(), - ]; - executeSteps = [ - new CosmosDBAccountCreateStep(), - new VerifyProvidersStep(['Microsoft.DocumentDB']) - ]; - } - return { promptSteps, executeSteps }; - } + public async getSubWizard( + context: IAzureDBWizardContext + ): Promise< + IWizardOptions + > { + let promptSteps: AzureWizardPromptStep< + IPostgresServerWizardContext | ICosmosDBWizardContext + >[]; + let executeSteps: AzureWizardExecuteStep< + IPostgresServerWizardContext | ICosmosDBWizardContext + >[]; + if ( + context.defaultExperience?.api === API.PostgresSingle || + context.defaultExperience?.api === API.PostgresFlexible + ) { + switch (context.defaultExperience?.api) { + case API.PostgresFlexible: + (context as IPostgresServerWizardContext).serverType = + PostgresServerType.Flexible; + break; + case API.PostgresSingle: + (context as IPostgresServerWizardContext).serverType = + PostgresServerType.Single; + break; + } + promptSteps = [ + new PostgresServerNameStep(), + new PostgresServerSkuStep(), + new PostgresServerCredUserStep(), + new PostgresServerCredPWStep(), + new PostgresServerConfirmPWStep(), + ]; + executeSteps = [ + new PostgresServerCreateStep(), + new PostgresServerSetCredentialsStep(), + new VerifyProvidersStep(["Microsoft.DBforPostgreSQL"]), + ]; + } else { + promptSteps = [ + new CosmosDBAccountNameStep(), + new CosmosDBAccountCapacityStep(), + ]; + executeSteps = [ + new CosmosDBAccountCreateStep(), + new VerifyProvidersStep(["Microsoft.DocumentDB"]), + ]; + } + return { promptSteps, executeSteps }; + } - public shouldPrompt(context: IAzureDBWizardContext): boolean { - return !context.defaultExperience; - } + public shouldPrompt(context: IAzureDBWizardContext): boolean { + return !context.defaultExperience; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts index b46453e3a..192e5fa54 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCapacityStep.ts @@ -3,38 +3,53 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../utils/localize'; -import { openUrl } from '../../utils/openUrl'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, +} from "@microsoft/vscode-azext-utils"; +import { localize } from "../../utils/localize"; +import { openUrl } from "../../utils/openUrl"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountCapacityStep extends AzureWizardPromptStep { + public async prompt(context: ICosmosDBWizardContext): Promise { + const placeHolder: string = localize( + "selectDBServerMsg", + "Select a capacity model." + ); + const picks: IAzureQuickPickItem[] = [ + { + label: localize("provisionedOption", "Provisioned Throughput"), + data: false, + }, + { label: localize("serverlessOption", "Serverless"), data: true }, + ]; + const learnMore: IAzureQuickPickItem = { + label: localize("learnMore", "$(link-external) Learn more..."), + data: undefined, + }; + picks.push(learnMore); + let pick: IAzureQuickPickItem; - public async prompt(context: ICosmosDBWizardContext): Promise { + do { + pick = await context.ui.showQuickPick(picks, { + placeHolder, + suppressPersistence: true, + }); + if (pick === learnMore) { + await openUrl("https://aka.ms/cosmos-models"); + } + } while (pick === learnMore); - const placeHolder: string = localize('selectDBServerMsg', 'Select a capacity model.') - const picks: IAzureQuickPickItem[] = [ - { label: localize('provisionedOption', 'Provisioned Throughput'), data: false }, - { label: localize('serverlessOption', 'Serverless'), data: true }, - ]; - const learnMore: IAzureQuickPickItem = { label: localize('learnMore', '$(link-external) Learn more...'), data: undefined }; - picks.push(learnMore); - let pick: IAzureQuickPickItem; + if (pick.data) { + context.isServerless = pick.data; + context.telemetry.properties.isServerless = pick.data + ? "true" + : "false"; + } + } - do { - pick = await context.ui.showQuickPick(picks, { placeHolder, suppressPersistence: true }); - if (pick === learnMore) { - await openUrl('https://aka.ms/cosmos-models'); - } - } while (pick === learnMore); - - if (pick.data) { - context.isServerless = pick.data; - context.telemetry.properties.isServerless = pick.data ? 'true' : 'false'; - } - } - - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return context.isServerless === undefined; - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return context.isServerless === undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts index 4bd469b84..f0eadf3a3 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountCreateStep.ts @@ -3,61 +3,81 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountCreateUpdateParameters } from '@azure/arm-cosmosdb/src/models'; -import { LocationListStep } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { Progress } from 'vscode'; -import { SERVERLESS_CAPABILITY_NAME } from '../../constants'; -import { ext } from '../../extensionVariables'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { localize } from '../../utils/localize'; -import { nonNullProp } from '../../utils/nonNull'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { DatabaseAccountCreateUpdateParameters } from "@azure/arm-cosmosdb/src/models"; +import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; +import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; +import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; +import { Progress } from "vscode"; +import { SERVERLESS_CAPABILITY_NAME } from "../../constants"; +import { ext } from "../../extensionVariables"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { localize } from "../../utils/localize"; +import { nonNullProp } from "../../utils/nonNull"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountCreateStep extends AzureWizardExecuteStep { - public priority: number = 130; - - public async execute(context: ICosmosDBWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { - const locationName: string = (await LocationListStep.getLocation(context)).name; - const defaultExperience = nonNullProp(context, 'defaultExperience'); - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const accountName = nonNullProp(context, 'newServerName'); - - const client = await createCosmosDBClient(context); - const creatingMessage: string = localize('creatingCosmosDBAccount', 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', accountName, defaultExperience.shortName); - ext.outputChannel.appendLog(creatingMessage); - progress.report({ message: creatingMessage }); - - const options: DatabaseAccountCreateUpdateParameters = { - location: locationName, - locations: [{ locationName: locationName }], - kind: defaultExperience.kind, - capabilities: [], - databaseAccountOfferType: 'Standard', - // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior - tags: { defaultExperience: nonNullProp(defaultExperience, 'tag') }, - }; - - if (defaultExperience?.api === 'MongoDB') { - options.apiProperties = { serverVersion: '3.6' }; - } - - if (defaultExperience.capability) { - options.capabilities?.push({ name: defaultExperience.capability }); - } - - if (context.isServerless) { - options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); - } - - context.databaseAccount = await client.databaseAccounts.beginCreateOrUpdateAndWait(rgName, accountName, options); - context.activityResult = context.databaseAccount as AppResource; - - ext.outputChannel.appendLog(`Successfully created Cosmos DB account "${accountName}".`); - } - - public shouldExecute(context: ICosmosDBWizardContext): boolean { - return !context.databaseAccount; - } + public priority: number = 130; + + public async execute( + context: ICosmosDBWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + const locationName: string = ( + await LocationListStep.getLocation(context) + ).name; + const defaultExperience = nonNullProp(context, "defaultExperience"); + const rgName: string = nonNullProp( + nonNullProp(context, "resourceGroup"), + "name" + ); + const accountName = nonNullProp(context, "newServerName"); + + const client = await createCosmosDBClient(context); + const creatingMessage: string = localize( + "creatingCosmosDBAccount", + 'Creating Cosmos DB account "{0}" with the "{1}" API... It should be ready in several minutes.', + accountName, + defaultExperience.shortName + ); + ext.outputChannel.appendLog(creatingMessage); + progress.report({ message: creatingMessage }); + + const options: DatabaseAccountCreateUpdateParameters = { + location: locationName, + locations: [{ locationName: locationName }], + kind: defaultExperience.kind, + capabilities: [], + databaseAccountOfferType: "Standard", + // Note: Setting this tag has no functional effect in the portal, but we'll keep doing it to imitate portal behavior + tags: { defaultExperience: nonNullProp(defaultExperience, "tag") }, + }; + + if (defaultExperience?.api === "MongoDB") { + options.apiProperties = { serverVersion: "3.6" }; + } + + if (defaultExperience.capability) { + options.capabilities?.push({ name: defaultExperience.capability }); + } + + if (context.isServerless) { + options.capabilities?.push({ name: SERVERLESS_CAPABILITY_NAME }); + } + + context.databaseAccount = + await client.databaseAccounts.beginCreateOrUpdateAndWait( + rgName, + accountName, + options + ); + context.activityResult = context.databaseAccount as AppResource; + + ext.outputChannel.appendLog( + `Successfully created Cosmos DB account "${accountName}".` + ); + } + + public shouldExecute(context: ICosmosDBWizardContext): boolean { + return !context.databaseAccount; + } } diff --git a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts index 87ef6be61..222736605 100644 --- a/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts +++ b/Source/tree/CosmosDBAccountWizard/CosmosDBAccountNameStep.ts @@ -3,47 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { createCosmosDBClient } from '../../utils/azureClients'; -import { ICosmosDBWizardContext } from './ICosmosDBWizardContext'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { + ResourceGroupListStep, + resourceGroupNamingRules, +} from "@microsoft/vscode-azext-azureutils"; +import { AzureNameStep } from "@microsoft/vscode-azext-utils"; +import { createCosmosDBClient } from "../../utils/azureClients"; +import { ICosmosDBWizardContext } from "./ICosmosDBWizardContext"; export class CosmosDBAccountNameStep extends AzureNameStep { + public async prompt(context: ICosmosDBWizardContext): Promise { + const client = await createCosmosDBClient(context); + context.newServerName = ( + await context.ui.showInputBox({ + placeHolder: "Account name", + prompt: "Provide a Cosmos DB account name", + validateInput: (name: string) => + validateCosmosDBAccountName(name, client), + }) + ).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName( + context, + context.newServerName, + resourceGroupNamingRules + ); + } - public async prompt(context: ICosmosDBWizardContext): Promise { - const client = await createCosmosDBClient(context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: "Account name", - prompt: "Provide a Cosmos DB account name", - validateInput: (name: string) => validateCosmosDBAccountName(name, client) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } + public shouldPrompt(context: ICosmosDBWizardContext): boolean { + return !context.newServerName; + } - public shouldPrompt(context: ICosmosDBWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: ICosmosDBWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } + protected async isRelatedNameAvailable( + context: ICosmosDBWizardContext, + name: string + ): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } } -async function validateCosmosDBAccountName(name: string, client: CosmosDBManagementClient): Promise { - name = name ? name.trim() : ''; +async function validateCosmosDBAccountName( + name: string, + client: CosmosDBManagementClient +): Promise { + name = name ? name.trim() : ""; - const min = 3; - const max = 31; + const min = 3; + const max = 31; - if (name.length < min || name.length > max) { - return `The name must be between ${min} and ${max} characters.`; - } else if (name.match(/[^a-z0-9-]/)) { - return "The name can only contain lowercase letters, numbers, and the '-' character."; - } else if ((await client.databaseAccounts.checkNameExists(name)).body) { - return `Account name "${name}" is not available.`; - } else { - return undefined; - } + if (name.length < min || name.length > max) { + return `The name must be between ${min} and ${max} characters.`; + } else if (name.match(/[^a-z0-9-]/)) { + return "The name can only contain lowercase letters, numbers, and the '-' character."; + } else if ((await client.databaseAccounts.checkNameExists(name)).body) { + return `Account name "${name}" is not available.`; + } else { + return undefined; + } } diff --git a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts index 61666a859..cc12a75ed 100644 --- a/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts +++ b/Source/tree/CosmosDBAccountWizard/ICosmosDBWizardContext.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { IAzureDBWizardContext } from '../IAzureDBWizardContext'; - -export interface ICosmosDBWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - - /** - * The newly created Cosmos DB account - * This will be defined after `CosmosDBAccountStep.execute` occurs. - */ - databaseAccount?: DatabaseAccountGetResults; - isServerless?: boolean; +import { DatabaseAccountGetResults } from "@azure/arm-cosmosdb"; +import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; +import { IAzureDBWizardContext } from "../IAzureDBWizardContext"; +export interface ICosmosDBWizardContext + extends IAzureDBWizardContext, + ExecuteActivityContext { + /** + * The newly created Cosmos DB account + * This will be defined after `CosmosDBAccountStep.execute` occurs. + */ + databaseAccount?: DatabaseAccountGetResults; + isServerless?: boolean; } diff --git a/Source/tree/IAzureDBWizardContext.ts b/Source/tree/IAzureDBWizardContext.ts index fd84ff0d5..5f6946275 100644 --- a/Source/tree/IAzureDBWizardContext.ts +++ b/Source/tree/IAzureDBWizardContext.ts @@ -3,12 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { Experience } from '../AzureDBExperiences'; +import { IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; +import { Experience } from "../AzureDBExperiences"; export interface IAzureDBWizardContext extends IResourceGroupWizardContext { - - newServerName?: string; - defaultExperience?: Experience; - + newServerName?: string; + defaultExperience?: Experience; } diff --git a/Source/tree/SubscriptionTreeItem.ts b/Source/tree/SubscriptionTreeItem.ts index 910d8d970..93cb2173a 100644 --- a/Source/tree/SubscriptionTreeItem.ts +++ b/Source/tree/SubscriptionTreeItem.ts @@ -3,156 +3,322 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { DatabaseAccountGetResults, DatabaseAccountListKeysResult } from '@azure/arm-cosmosdb/src/models'; -import { getResourceGroupFromId, ILocationWizardContext, LocationListStep, ResourceGroupListStep, SubscriptionTreeItemBase, uiUtils } from '@microsoft/vscode-azext-azureutils'; -import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, AzureWizardPromptStep, IActionContext } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { API, Experience, getExperienceLabel, tryGetExperience } from '../AzureDBExperiences'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { + DatabaseAccountGetResults, + DatabaseAccountListKeysResult, +} from "@azure/arm-cosmosdb/src/models"; +import { + getResourceGroupFromId, + ILocationWizardContext, + LocationListStep, + ResourceGroupListStep, + SubscriptionTreeItemBase, + uiUtils, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtParentTreeItem, + AzExtTreeItem, + AzureWizard, + AzureWizardPromptStep, + IActionContext, +} from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { + API, + Experience, + getExperienceLabel, + tryGetExperience, +} from "../AzureDBExperiences"; import { DocDBAccountTreeItem } from "../docdb/tree/DocDBAccountTreeItem"; -import { ext } from '../extensionVariables'; -import { tryGetGremlinEndpointFromAzure } from '../graph/gremlinEndpoints'; +import { ext } from "../extensionVariables"; +import { tryGetGremlinEndpointFromAzure } from "../graph/gremlinEndpoints"; import { GraphAccountTreeItem } from "../graph/tree/GraphAccountTreeItem"; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { PostgresAbstractServer, PostgresServerType } from '../postgres/abstract/models'; -import { IPostgresServerWizardContext } from '../postgres/commands/createPostgresServer/IPostgresServerWizardContext'; -import { createPostgresConnectionString, ParsedPostgresConnectionString, parsePostgresConnectionString } from '../postgres/postgresConnectionStrings'; -import { PostgresServerTreeItem } from '../postgres/tree/PostgresServerTreeItem'; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { + PostgresAbstractServer, + PostgresServerType, +} from "../postgres/abstract/models"; +import { IPostgresServerWizardContext } from "../postgres/commands/createPostgresServer/IPostgresServerWizardContext"; +import { + createPostgresConnectionString, + ParsedPostgresConnectionString, + parsePostgresConnectionString, +} from "../postgres/postgresConnectionStrings"; +import { PostgresServerTreeItem } from "../postgres/tree/PostgresServerTreeItem"; import { TableAccountTreeItem } from "../table/tree/TableAccountTreeItem"; -import { createActivityContext } from '../utils/activityUtils'; -import { createCosmosDBClient, createPostgreSQLClient, createPostgreSQLFlexibleClient } from '../utils/azureClients'; -import { localize } from '../utils/localize'; -import { nonNullProp } from '../utils/nonNull'; -import { AzureDBAPIStep } from './AzureDBAPIStep'; -import { ICosmosDBWizardContext } from './CosmosDBAccountWizard/ICosmosDBWizardContext'; +import { createActivityContext } from "../utils/activityUtils"; +import { + createCosmosDBClient, + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../utils/azureClients"; +import { localize } from "../utils/localize"; +import { nonNullProp } from "../utils/nonNull"; +import { AzureDBAPIStep } from "./AzureDBAPIStep"; +import { ICosmosDBWizardContext } from "./CosmosDBAccountWizard/ICosmosDBWizardContext"; export class SubscriptionTreeItem extends SubscriptionTreeItemBase { - public childTypeLabel: string = 'Account'; - - public hasMoreChildrenImpl(): boolean { - return false; - } - - public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise { - - //Postgres - const postgresSingleClient = await createPostgreSQLClient([context, this.subscription]); - const postgresFlexibleClient = await createPostgreSQLFlexibleClient([context, this.subscription]); - const postgresServers: PostgresAbstractServer[] = [ - ...(await uiUtils.listAllIterator(postgresSingleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Single })), - ...(await uiUtils.listAllIterator(postgresFlexibleClient.servers.list())).map(s => Object.assign(s, { serverType: PostgresServerType.Flexible })), - ]; - - const treeItemPostgres: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - postgresServers, - 'invalidPostgreSQLAccount', - async (server: PostgresAbstractServer) => await SubscriptionTreeItem.initPostgresChild(server, this), - (server: PostgresAbstractServer) => server.name - ); - - //CosmosDB - const client = await createCosmosDBClient([context, this]); - const accounts = await uiUtils.listAllIterator(client.databaseAccounts.list()); - const treeItem: AzExtTreeItem[] = await this.createTreeItemsWithErrorHandling( - accounts, - 'invalidCosmosDBAccount', - async (db: DatabaseAccountGetResults) => await SubscriptionTreeItem.initCosmosDBChild(client, db, this), - (db: DatabaseAccountGetResults) => db.name - ); - - treeItem.push(...treeItemPostgres); - return treeItem; - } - - public static async createChild(context: IActionContext & { defaultExperience?: Experience }, node: SubscriptionTreeItem): Promise { - const client = await createCosmosDBClient([context, node.subscription]); - const wizardContext: IPostgresServerWizardContext & ICosmosDBWizardContext = Object.assign(context, node.subscription, { ...(await createActivityContext()) }); - - const promptSteps: AzureWizardPromptStep[] = [ - new AzureDBAPIStep(), - new ResourceGroupListStep() - ]; - LocationListStep.addStep(wizardContext, promptSteps); - - const wizard = new AzureWizard(wizardContext, { - promptSteps, - executeSteps: [], - title: localize('createDBServerMsg', 'Create new Azure Database Server') - }); - - await wizard.prompt(); - - wizardContext.telemetry.properties.defaultExperience = wizardContext.defaultExperience?.api; - - const newServerName: string = nonNullProp(wizardContext, 'newServerName'); - wizardContext.activityTitle = localize('createDBServerMsgActivityTitle', 'Create new Azure Database Server "{0}"', newServerName); - - await wizard.execute(); - await ext.rgApi.appResourceTree.refresh(context); - if (wizardContext.defaultExperience?.api === API.PostgresSingle || wizardContext.defaultExperience?.api === API.PostgresFlexible) { - const createMessage: string = localize('createdServerOutput', 'Successfully created PostgreSQL server "{0}".', wizardContext.newServerName); - void vscode.window.showInformationMessage(createMessage); - ext.outputChannel.appendLog(createMessage); - const server = nonNullProp(wizardContext, 'server'); - const host = nonNullProp(server, 'fullyQualifiedDomainName'); - const username: string = wizardContext.serverType === PostgresServerType.Flexible ? nonNullProp(wizardContext, 'shortUserName') : nonNullProp(wizardContext, 'longUserName'); - const password: string = nonNullProp(wizardContext, 'adminPassword'); - const connectionString: string = createPostgresConnectionString(host, undefined, username, password); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(node, parsedCS, server); - } else { - return await SubscriptionTreeItem.initCosmosDBChild(client, nonNullProp(wizardContext, 'databaseAccount'), node); - } - } - - public isAncestorOfImpl(contextValue: string | RegExp): boolean { - return typeof contextValue !== 'string' || !/attached/i.test(contextValue); - } - - public static async initCosmosDBChild(client: CosmosDBManagementClient, databaseAccount: DatabaseAccountGetResults, parent: AzExtParentTreeItem): Promise { - const experience = tryGetExperience(databaseAccount); - const id: string = nonNullProp(databaseAccount, 'id'); - const name: string = nonNullProp(databaseAccount, 'name'); - const documentEndpoint: string = nonNullProp(databaseAccount, 'documentEndpoint'); - - const resourceGroup: string = getResourceGroupFromId(id); - const accountKindLabel = getExperienceLabel(databaseAccount); - const label: string = name + (accountKindLabel ? ` (${accountKindLabel})` : ``); - const isEmulator: boolean = false; - - if (experience && experience.api === "MongoDB") { - const result = await client.databaseAccounts.listConnectionStrings(resourceGroup, name); - const connectionString: URL = new URL(nonNullProp(nonNullProp(result, 'connectionStrings')[0], 'connectionString')); - // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites - // but the newer node.js drivers started breaking this - const searchParam: string = 'retrywrites'; - if (!connectionString.searchParams.has(searchParam)) { - connectionString.searchParams.set(searchParam, 'false'); - } - - // Use the default connection string - return new MongoAccountTreeItem(parent, id, label, connectionString.toString(), isEmulator, databaseAccount); - } else { - const keyResult: DatabaseAccountListKeysResult = await client.databaseAccounts.listKeys(resourceGroup, name); - const primaryMasterKey: string = nonNullProp(keyResult, 'primaryMasterKey'); - switch (experience && experience.api) { - case "Table": - return new TableAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - case "Graph": { - const gremlinEndpoint = await tryGetGremlinEndpointFromAzure(client, resourceGroup, name); - return new GraphAccountTreeItem(parent, id, label, documentEndpoint, gremlinEndpoint, primaryMasterKey, isEmulator, databaseAccount); - } - case "Core": - default: - // Default to DocumentDB, the base type for all Cosmos DB Accounts - return new DocDBAccountTreeItem(parent, id, label, documentEndpoint, primaryMasterKey, isEmulator, databaseAccount); - - } - } - } - public static async initPostgresChild(server: PostgresAbstractServer, parent: AzExtParentTreeItem): Promise { - const connectionString: string = createPostgresConnectionString(nonNullProp(server, 'fullyQualifiedDomainName')); - const parsedCS: ParsedPostgresConnectionString = parsePostgresConnectionString(connectionString); - return new PostgresServerTreeItem(parent, parsedCS, server); - } + public childTypeLabel: string = "Account"; + + public hasMoreChildrenImpl(): boolean { + return false; + } + + public async loadMoreChildrenImpl( + _clearCache: boolean, + context: IActionContext + ): Promise { + //Postgres + const postgresSingleClient = await createPostgreSQLClient([ + context, + this.subscription, + ]); + const postgresFlexibleClient = await createPostgreSQLFlexibleClient([ + context, + this.subscription, + ]); + const postgresServers: PostgresAbstractServer[] = [ + ...( + await uiUtils.listAllIterator( + postgresSingleClient.servers.list() + ) + ).map((s) => + Object.assign(s, { serverType: PostgresServerType.Single }) + ), + ...( + await uiUtils.listAllIterator( + postgresFlexibleClient.servers.list() + ) + ).map((s) => + Object.assign(s, { serverType: PostgresServerType.Flexible }) + ), + ]; + + const treeItemPostgres: AzExtTreeItem[] = + await this.createTreeItemsWithErrorHandling( + postgresServers, + "invalidPostgreSQLAccount", + async (server: PostgresAbstractServer) => + await SubscriptionTreeItem.initPostgresChild(server, this), + (server: PostgresAbstractServer) => server.name + ); + + //CosmosDB + const client = await createCosmosDBClient([context, this]); + const accounts = await uiUtils.listAllIterator( + client.databaseAccounts.list() + ); + const treeItem: AzExtTreeItem[] = + await this.createTreeItemsWithErrorHandling( + accounts, + "invalidCosmosDBAccount", + async (db: DatabaseAccountGetResults) => + await SubscriptionTreeItem.initCosmosDBChild( + client, + db, + this + ), + (db: DatabaseAccountGetResults) => db.name + ); + + treeItem.push(...treeItemPostgres); + return treeItem; + } + + public static async createChild( + context: IActionContext & { defaultExperience?: Experience }, + node: SubscriptionTreeItem + ): Promise { + const client = await createCosmosDBClient([context, node.subscription]); + const wizardContext: IPostgresServerWizardContext & + ICosmosDBWizardContext = Object.assign(context, node.subscription, { + ...(await createActivityContext()), + }); + + const promptSteps: AzureWizardPromptStep[] = [ + new AzureDBAPIStep(), + new ResourceGroupListStep(), + ]; + LocationListStep.addStep(wizardContext, promptSteps); + + const wizard = new AzureWizard(wizardContext, { + promptSteps, + executeSteps: [], + title: localize( + "createDBServerMsg", + "Create new Azure Database Server" + ), + }); + + await wizard.prompt(); + + wizardContext.telemetry.properties.defaultExperience = + wizardContext.defaultExperience?.api; + + const newServerName: string = nonNullProp( + wizardContext, + "newServerName" + ); + wizardContext.activityTitle = localize( + "createDBServerMsgActivityTitle", + 'Create new Azure Database Server "{0}"', + newServerName + ); + + await wizard.execute(); + await ext.rgApi.appResourceTree.refresh(context); + if ( + wizardContext.defaultExperience?.api === API.PostgresSingle || + wizardContext.defaultExperience?.api === API.PostgresFlexible + ) { + const createMessage: string = localize( + "createdServerOutput", + 'Successfully created PostgreSQL server "{0}".', + wizardContext.newServerName + ); + void vscode.window.showInformationMessage(createMessage); + ext.outputChannel.appendLog(createMessage); + const server = nonNullProp(wizardContext, "server"); + const host = nonNullProp(server, "fullyQualifiedDomainName"); + const username: string = + wizardContext.serverType === PostgresServerType.Flexible + ? nonNullProp(wizardContext, "shortUserName") + : nonNullProp(wizardContext, "longUserName"); + const password: string = nonNullProp( + wizardContext, + "adminPassword" + ); + const connectionString: string = createPostgresConnectionString( + host, + undefined, + username, + password + ); + const parsedCS: ParsedPostgresConnectionString = + parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(node, parsedCS, server); + } else { + return await SubscriptionTreeItem.initCosmosDBChild( + client, + nonNullProp(wizardContext, "databaseAccount"), + node + ); + } + } + + public isAncestorOfImpl(contextValue: string | RegExp): boolean { + return ( + typeof contextValue !== "string" || !/attached/i.test(contextValue) + ); + } + + public static async initCosmosDBChild( + client: CosmosDBManagementClient, + databaseAccount: DatabaseAccountGetResults, + parent: AzExtParentTreeItem + ): Promise { + const experience = tryGetExperience(databaseAccount); + const id: string = nonNullProp(databaseAccount, "id"); + const name: string = nonNullProp(databaseAccount, "name"); + const documentEndpoint: string = nonNullProp( + databaseAccount, + "documentEndpoint" + ); + + const resourceGroup: string = getResourceGroupFromId(id); + const accountKindLabel = getExperienceLabel(databaseAccount); + const label: string = + name + (accountKindLabel ? ` (${accountKindLabel})` : ``); + const isEmulator: boolean = false; + + if (experience && experience.api === "MongoDB") { + const result = await client.databaseAccounts.listConnectionStrings( + resourceGroup, + name + ); + const connectionString: URL = new URL( + nonNullProp( + nonNullProp(result, "connectionStrings")[0], + "connectionString" + ) + ); + // for any Mongo connectionString, append this query param because the Cosmos Mongo API v3.6 doesn't support retrywrites + // but the newer node.js drivers started breaking this + const searchParam: string = "retrywrites"; + if (!connectionString.searchParams.has(searchParam)) { + connectionString.searchParams.set(searchParam, "false"); + } + + // Use the default connection string + return new MongoAccountTreeItem( + parent, + id, + label, + connectionString.toString(), + isEmulator, + databaseAccount + ); + } else { + const keyResult: DatabaseAccountListKeysResult = + await client.databaseAccounts.listKeys(resourceGroup, name); + const primaryMasterKey: string = nonNullProp( + keyResult, + "primaryMasterKey" + ); + switch (experience && experience.api) { + case "Table": + return new TableAccountTreeItem( + parent, + id, + label, + documentEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + case "Graph": { + const gremlinEndpoint = + await tryGetGremlinEndpointFromAzure( + client, + resourceGroup, + name + ); + return new GraphAccountTreeItem( + parent, + id, + label, + documentEndpoint, + gremlinEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + } + case "Core": + default: + // Default to DocumentDB, the base type for all Cosmos DB Accounts + return new DocDBAccountTreeItem( + parent, + id, + label, + documentEndpoint, + primaryMasterKey, + isEmulator, + databaseAccount + ); + } + } + } + public static async initPostgresChild( + server: PostgresAbstractServer, + parent: AzExtParentTreeItem + ): Promise { + const connectionString: string = createPostgresConnectionString( + nonNullProp(server, "fullyQualifiedDomainName") + ); + const parsedCS: ParsedPostgresConnectionString = + parsePostgresConnectionString(connectionString); + return new PostgresServerTreeItem(parent, parsedCS, server); + } } diff --git a/Source/utils/InteractiveChildProcess.ts b/Source/utils/InteractiveChildProcess.ts index 26129b342..1cd1848e5 100644 --- a/Source/utils/InteractiveChildProcess.ts +++ b/Source/utils/InteractiveChildProcess.ts @@ -3,174 +3,194 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { parseError } from '@microsoft/vscode-azext-utils'; -import * as cp from 'child_process'; -import * as os from 'os'; -import { isNumber } from 'util'; -import * as vscode from 'vscode'; -import { Event, EventEmitter } from 'vscode'; -import { improveError } from './improveError'; +import { parseError } from "@microsoft/vscode-azext-utils"; +import * as cp from "child_process"; +import * as os from "os"; +import { isNumber } from "util"; +import * as vscode from "vscode"; +import { Event, EventEmitter } from "vscode"; +import { improveError } from "./improveError"; // We add these when we display to the output window -const stdInPrefix = '> '; -const stdErrPrefix = 'ERR> '; -const errorPrefix = 'Error running process: '; +const stdInPrefix = "> "; +const stdErrPrefix = "ERR> "; +const errorPrefix = "Error running process: "; const processStartupTimeout = 60; export interface IInteractiveChildProcessOptions { - command: string; - args: string[]; - outputChannel?: vscode.OutputChannel; - workingDirectory?: string; - showTimeInOutputChannel?: boolean; - outputFilterSearch?: RegExp; - outputFilterReplace?: string; + command: string; + args: string[]; + outputChannel?: vscode.OutputChannel; + workingDirectory?: string; + showTimeInOutputChannel?: boolean; + outputFilterSearch?: RegExp; + outputFilterReplace?: string; } export class InteractiveChildProcess { - private _childProc: cp.ChildProcess; - private readonly _options: IInteractiveChildProcessOptions; - private _startTime: number; - private _error: unknown; - private _isKilling: boolean; - - private readonly _onStdOutEmitter: EventEmitter = new EventEmitter(); - private readonly _onStdErrEmitter: EventEmitter = new EventEmitter(); - private readonly _onErrorEmitter: EventEmitter = new EventEmitter(); - - private constructor(options: IInteractiveChildProcessOptions) { - this._options = options; - } - - public get onStdOut(): Event { - return this._onStdOutEmitter.event; - } - - public get onStdErr(): Event { - return this._onStdErrEmitter.event; - } - - public get onError(): Event { - return this._onErrorEmitter.event; - } - - public static async create(options: IInteractiveChildProcessOptions): Promise { - const child: InteractiveChildProcess = new InteractiveChildProcess(options); - await child.startCore(); - return child; - } - - public kill(): void { - this._isKilling = true; - this._childProc.kill(); - } - - public writeLine(text: string): void { - this.writeLineToOutputChannel(text, stdInPrefix); - this._childProc.stdin?.write(text + os.EOL); - } - - private async startCore(): Promise { - this._startTime = Date.now(); - const formattedArgs: string = this._options.args.join(' '); - - const workingDirectory = this._options.workingDirectory || os.tmpdir(); - const options: cp.SpawnOptions = { - cwd: workingDirectory, - - // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since - // the command is run in the shell, handling errors (such as command not found) would be more indirect, - // coming through STDERR instead of the error event - shell: false - }; - - this.writeLineToOutputChannel(`Starting executable: "${this._options.command}" ${formattedArgs}`); - this._childProc = cp.spawn(this._options.command, this._options.args, options); - - this._childProc.stdout?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdOutEmitter.fire(text); - this.writeLineToOutputChannel(text); - }); - - this._childProc.stderr?.on('data', (data: string | Buffer) => { - const text = data.toString(); - this._onStdErrEmitter.fire(text); - this.writeLineToOutputChannel(text, stdErrPrefix); - }); - - this._childProc.on('error', (error: unknown) => { - const improvedError = improveError(error); - this.setError(improvedError); - }); - - this._childProc.on('close', (code: number | null) => { - if (isNumber(code) && code !== 0) { - this.setError(`The process exited with code ${code}.`); - } else if (!this._isKilling) { - this.setError(`The process exited prematurely.`); - } - }); - - // Wait for the process to start up - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - await new Promise(async (resolve, reject) => { - const started = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - if (!!this._error || this._isKilling) { - reject(this._error); - break; - } else if (this._childProc.pid) { - resolve(); - break; - } else { - if (Date.now() > started + processStartupTimeout) { - reject("The process did not start in a timely manner"); - break; - } - await delay(50); - } - } - }); - } - - private writeLineToOutputChannel(text: string, displayPrefix?: string): void { - const filteredText = this.filterText(text); - const changedIntoEmptyString = (filteredText !== text && filteredText === ''); - - if (!changedIntoEmptyString) { - text = filteredText; - if (this._options.outputChannel) { - if (this._options.showTimeInOutputChannel) { - const ms = Date.now() - this._startTime; - text = `${ms}ms: ${text}`; - } - - text = (displayPrefix || "") + text; - this._options.outputChannel.appendLine(text); - } - } - } - - private setError(error: unknown): void { - this.writeLineToOutputChannel(parseError(error).message, errorPrefix); - this._error = this._error || error; - this._onErrorEmitter.fire(error); - } - - private filterText(text: string): string { - if (this._options.outputFilterSearch) { - return text.replace(this._options.outputFilterSearch, this._options.outputFilterReplace || ""); - } - - return text; - } + private _childProc: cp.ChildProcess; + private readonly _options: IInteractiveChildProcessOptions; + private _startTime: number; + private _error: unknown; + private _isKilling: boolean; + + private readonly _onStdOutEmitter: EventEmitter = + new EventEmitter(); + private readonly _onStdErrEmitter: EventEmitter = + new EventEmitter(); + private readonly _onErrorEmitter: EventEmitter = + new EventEmitter(); + + private constructor(options: IInteractiveChildProcessOptions) { + this._options = options; + } + + public get onStdOut(): Event { + return this._onStdOutEmitter.event; + } + + public get onStdErr(): Event { + return this._onStdErrEmitter.event; + } + + public get onError(): Event { + return this._onErrorEmitter.event; + } + + public static async create( + options: IInteractiveChildProcessOptions + ): Promise { + const child: InteractiveChildProcess = new InteractiveChildProcess( + options + ); + await child.startCore(); + return child; + } + + public kill(): void { + this._isKilling = true; + this._childProc.kill(); + } + + public writeLine(text: string): void { + this.writeLineToOutputChannel(text, stdInPrefix); + this._childProc.stdin?.write(text + os.EOL); + } + + private async startCore(): Promise { + this._startTime = Date.now(); + const formattedArgs: string = this._options.args.join(" "); + + const workingDirectory = this._options.workingDirectory || os.tmpdir(); + const options: cp.SpawnOptions = { + cwd: workingDirectory, + + // Using shell=true would mean that we can pass paths that will be resolved by the shell, but since + // the command is run in the shell, handling errors (such as command not found) would be more indirect, + // coming through STDERR instead of the error event + shell: false, + }; + + this.writeLineToOutputChannel( + `Starting executable: "${this._options.command}" ${formattedArgs}` + ); + this._childProc = cp.spawn( + this._options.command, + this._options.args, + options + ); + + this._childProc.stdout?.on("data", (data: string | Buffer) => { + const text = data.toString(); + this._onStdOutEmitter.fire(text); + this.writeLineToOutputChannel(text); + }); + + this._childProc.stderr?.on("data", (data: string | Buffer) => { + const text = data.toString(); + this._onStdErrEmitter.fire(text); + this.writeLineToOutputChannel(text, stdErrPrefix); + }); + + this._childProc.on("error", (error: unknown) => { + const improvedError = improveError(error); + this.setError(improvedError); + }); + + this._childProc.on("close", (code: number | null) => { + if (isNumber(code) && code !== 0) { + this.setError(`The process exited with code ${code}.`); + } else if (!this._isKilling) { + this.setError(`The process exited prematurely.`); + } + }); + + // Wait for the process to start up + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + await new Promise(async (resolve, reject) => { + const started = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + if (!!this._error || this._isKilling) { + reject(this._error); + break; + } else if (this._childProc.pid) { + resolve(); + break; + } else { + if (Date.now() > started + processStartupTimeout) { + reject("The process did not start in a timely manner"); + break; + } + await delay(50); + } + } + }); + } + + private writeLineToOutputChannel( + text: string, + displayPrefix?: string + ): void { + const filteredText = this.filterText(text); + const changedIntoEmptyString = + filteredText !== text && filteredText === ""; + + if (!changedIntoEmptyString) { + text = filteredText; + if (this._options.outputChannel) { + if (this._options.showTimeInOutputChannel) { + const ms = Date.now() - this._startTime; + text = `${ms}ms: ${text}`; + } + + text = (displayPrefix || "") + text; + this._options.outputChannel.appendLine(text); + } + } + } + + private setError(error: unknown): void { + this.writeLineToOutputChannel(parseError(error).message, errorPrefix); + this._error = this._error || error; + this._onErrorEmitter.fire(error); + } + + private filterText(text: string): string { + if (this._options.outputFilterSearch) { + return text.replace( + this._options.outputFilterSearch, + this._options.outputFilterReplace || "" + ); + } + + return text; + } } async function delay(milliseconds: number): Promise { - return new Promise(resolve => { - setTimeout(resolve, milliseconds); - }); + return new Promise((resolve) => { + setTimeout(resolve, milliseconds); + }); } diff --git a/Source/utils/activityUtils.ts b/Source/utils/activityUtils.ts index fefd2fe00..d90c436cd 100644 --- a/Source/utils/activityUtils.ts +++ b/Source/utils/activityUtils.ts @@ -8,8 +8,13 @@ import { ext } from "../extensionVariables"; import { getWorkspaceSetting } from "./settingUtils"; export async function createActivityContext(): Promise { - return { - registerActivity: async (activity) => ext.rgApi.registerActivity(activity), - suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), - }; + return { + registerActivity: async (activity) => + ext.rgApi.registerActivity(activity), + suppressNotification: await getWorkspaceSetting( + "suppressActivityNotifications", + undefined, + "azureResourceGroups" + ), + }; } diff --git a/Source/utils/array.ts b/Source/utils/array.ts index 06f095e8d..5d779a53a 100644 --- a/Source/utils/array.ts +++ b/Source/utils/array.ts @@ -4,11 +4,21 @@ *--------------------------------------------------------------------------------------------*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function filterType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T[] { - return arr ? arr.filter(element => element instanceof genericConstructor) : []; +export function filterType( + arr: Object[] | undefined, + genericConstructor: new (...args: any[]) => T +): T[] { + return arr + ? arr.filter((element) => element instanceof genericConstructor) + : []; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function findType(arr: Object[] | undefined, genericConstructor: new (...args: any[]) => T): T | undefined { - return arr && arr.find(element => element instanceof genericConstructor); +export function findType( + arr: Object[] | undefined, + genericConstructor: new (...args: any[]) => T +): T | undefined { + return ( + arr && arr.find((element) => element instanceof genericConstructor) + ); } diff --git a/Source/utils/azureClients.ts b/Source/utils/azureClients.ts index 9be19e959..c2f44bd1c 100644 --- a/Source/utils/azureClients.ts +++ b/Source/utils/azureClients.ts @@ -3,22 +3,41 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CosmosDBManagementClient } from '@azure/arm-cosmosdb'; -import { PostgreSQLManagementClient } from '@azure/arm-postgresql'; -import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from '@azure/arm-postgresql-flexible'; -import { AzExtClientContext, createAzureClient } from '@microsoft/vscode-azext-azureutils'; +import { CosmosDBManagementClient } from "@azure/arm-cosmosdb"; +import { PostgreSQLManagementClient } from "@azure/arm-postgresql"; +import { PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient } from "@azure/arm-postgresql-flexible"; +import { + AzExtClientContext, + createAzureClient, +} from "@microsoft/vscode-azext-azureutils"; // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript -export async function createCosmosDBClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-cosmosdb')).CosmosDBManagementClient); +export async function createCosmosDBClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-cosmosdb")).CosmosDBManagementClient + ); } -export async function createPostgreSQLClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql')).PostgreSQLManagementClient); +export async function createPostgreSQLClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-postgresql")).PostgreSQLManagementClient + ); } -export async function createPostgreSQLFlexibleClient(context: AzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-postgresql-flexible')).PostgreSQLManagementClient); +export async function createPostgreSQLFlexibleClient( + context: AzExtClientContext +): Promise { + return createAzureClient( + context, + (await import("@azure/arm-postgresql-flexible")) + .PostgreSQLManagementClient + ); } diff --git a/Source/utils/azureUtils.ts b/Source/utils/azureUtils.ts index b0017314b..0e067aa68 100644 --- a/Source/utils/azureUtils.ts +++ b/Source/utils/azureUtils.ts @@ -4,11 +4,13 @@ *--------------------------------------------------------------------------------------------*/ export function getDatabaseAccountNameFromId(id: string): string { - const matches: RegExpMatchArray | null = id.match(/\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/); + const matches: RegExpMatchArray | null = id.match( + /\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/(.*)\/databaseAccounts\/(.*)/ + ); - if (!matches || matches.length < 5) { - throw new Error('Invalid Azure Resource Id'); - } + if (!matches || matches.length < 5) { + throw new Error("Invalid Azure Resource Id"); + } - return matches[4]; + return matches[4]; } diff --git a/Source/utils/cp.ts b/Source/utils/cp.ts index 660dc3068..7f7d94117 100644 --- a/Source/utils/cp.ts +++ b/Source/utils/cp.ts @@ -3,12 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from 'child_process'; +import * as cp from "child_process"; -export async function commandSucceeds(command: string, ...args: string[]): Promise { - return await new Promise(resolve => { - cp.spawn(command, args) - .on('error', _error => resolve(false)) - .on('exit', code => resolve(code === 0)); - }); +export async function commandSucceeds( + command: string, + ...args: string[] +): Promise { + return await new Promise((resolve) => { + cp.spawn(command, args) + .on("error", (_error) => resolve(false)) + .on("exit", (code) => resolve(code === 0)); + }); } diff --git a/Source/utils/getIp.ts b/Source/utils/getIp.ts index 20d22e989..d3085ea52 100644 --- a/Source/utils/getIp.ts +++ b/Source/utils/getIp.ts @@ -1,61 +1,73 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import { sendRequestWithTimeout } from '@microsoft/vscode-azext-azureutils'; -import { IActionContext } from '@microsoft/vscode-azext-utils'; -import { isIPv4 } from 'net'; -import { localize } from './localize'; - -export function isIpInRanges(ip: string, ranges: { startIpAddress: string, endIpAddress: string }[]): boolean { - const ipNum = ipToNum(ip); - return ranges.some((range) => { - const startIpNum = ipToNum(range.startIpAddress); - const endIpNum = ipToNum(range.endIpAddress); - return startIpNum <= ipNum && ipNum <= endIpNum; - }); + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { sendRequestWithTimeout } from "@microsoft/vscode-azext-azureutils"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { isIPv4 } from "net"; +import { localize } from "./localize"; + +export function isIpInRanges( + ip: string, + ranges: { startIpAddress: string; endIpAddress: string }[] +): boolean { + const ipNum = ipToNum(ip); + return ranges.some((range) => { + const startIpNum = ipToNum(range.startIpAddress); + const endIpNum = ipToNum(range.endIpAddress); + return startIpNum <= ipNum && ipNum <= endIpNum; + }); } export async function getPublicIpv4(context: IActionContext): Promise { - const methods: (() => Promise)[] = [ - () => getPublicIpv4Https(context, 'https://api.ipify.org/'), - () => getPublicIpv4Https(context, 'https://ipv4.icanhazip.com/'), - ]; - - let lastError: unknown; - for (const getIp of methods) { - try { - return await getIp(); - } catch (e: unknown) { - lastError = e; - } - } - - throw lastError; + const methods: (() => Promise)[] = [ + () => getPublicIpv4Https(context, "https://api.ipify.org/"), + () => getPublicIpv4Https(context, "https://ipv4.icanhazip.com/"), + ]; + + let lastError: unknown; + for (const getIp of methods) { + try { + return await getIp(); + } catch (e: unknown) { + lastError = e; + } + } + + throw lastError; } -const failedToGetIp = localize('failedToGetIp', 'Failed to get public IP'); +const failedToGetIp = localize("failedToGetIp", "Failed to get public IP"); function ipToNum(ip: string) { - return Number( - ip.split(".") - .map(d => ("000" + d).substring(-3)) - .join("") - ); + return Number( + ip + .split(".") + .map((d) => ("000" + d).substring(-3)) + .join("") + ); } -async function getPublicIpv4Https(context: IActionContext, url: string): Promise { - const req = await sendRequestWithTimeout(context, { - method: 'GET', - url, - }, 5000, undefined); +async function getPublicIpv4Https( + context: IActionContext, + url: string +): Promise { + const req = await sendRequestWithTimeout( + context, + { + method: "GET", + url, + }, + 5000, + undefined + ); - const ip = req.bodyAsText; + const ip = req.bodyAsText; - if (!ip || !isIPv4(ip)) { - throw new Error(failedToGetIp); - } + if (!ip || !isIPv4(ip)) { + throw new Error(failedToGetIp); + } - return ip; + return ip; } diff --git a/Source/utils/getSecretStorageKey.ts b/Source/utils/getSecretStorageKey.ts index 8e404f554..d04de6cea 100644 --- a/Source/utils/getSecretStorageKey.ts +++ b/Source/utils/getSecretStorageKey.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ export function getSecretStorageKey(serviceName: string, id: string): string { - return `${serviceName}.${id}`; + return `${serviceName}.${id}`; } diff --git a/Source/utils/improveError.ts b/Source/utils/improveError.ts index 27ff1f014..08f0bedaf 100644 --- a/Source/utils/improveError.ts +++ b/Source/utils/improveError.ts @@ -6,12 +6,12 @@ import { parseError } from "@microsoft/vscode-azext-utils"; export function improveError(error: unknown): unknown { - const message = parseError(error).message; - // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" - const match = message.match(/spawn (.*) ENOENT/); - if (match) { - return new Error(`Could not find ${match[1]}`); - } + const message = parseError(error).message; + // Example: "spawn c:\Program Files\MongoDB\Server\4.0\bin\mongo.exe ENOENT" + const match = message.match(/spawn (.*) ENOENT/); + if (match) { + return new Error(`Could not find ${match[1]}`); + } - return error; + return error; } diff --git a/Source/utils/localize.ts b/Source/utils/localize.ts index 2aee3fa12..76d8fbf4d 100644 --- a/Source/utils/localize.ts +++ b/Source/utils/localize.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vscode-nls'; +import * as nls from "vscode-nls"; export const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Source/utils/nonNull.ts b/Source/utils/nonNull.ts index d7104b4f8..e9437afc9 100644 --- a/Source/utils/nonNull.ts +++ b/Source/utils/nonNull.ts @@ -3,39 +3,52 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { isNullOrUndefined } from 'util'; +import { isNullOrUndefined } from "util"; /** * Retrieves a property by name from an object and checks that it's not null and not undefined. It is strongly typed * for the property and will give a compile error if the given name is not a property of the source. */ -export function nonNullProp(source: TSource, name: TKey): NonNullable { - const value: NonNullable = >source[name]; - return nonNullValue(value, name); +export function nonNullProp( + source: TSource, + name: TKey +): NonNullable { + const value: NonNullable = >( + source[name] + ); + return nonNullValue(value, name); } /** * Validates that a given value is not null and not undefined. */ -export function nonNullValue(value: T | undefined | null, propertyNameOrMessage?: string): T { - if (isNullOrUndefined(value)) { - throw new Error( - 'Internal error: Expected value to be neither null nor undefined' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } +export function nonNullValue( + value: T | undefined | null, + propertyNameOrMessage?: string +): T { + if (isNullOrUndefined(value)) { + throw new Error( + "Internal error: Expected value to be neither null nor undefined" + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") + ); + } - return value; + return value; } /** * Validates that a given string is not null, undefined, nor empty */ -export function nonNullOrEmptyValue(value: string | undefined, propertyNameOrMessage?: string): string { - if (!value) { - throw new Error( - 'Internal error: Expected value to be neither null, undefined, nor empty' - + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : '')); - } +export function nonNullOrEmptyValue( + value: string | undefined, + propertyNameOrMessage?: string +): string { + if (!value) { + throw new Error( + "Internal error: Expected value to be neither null, undefined, nor empty" + + (propertyNameOrMessage ? `: ${propertyNameOrMessage}` : "") + ); + } - return value; + return value; } diff --git a/Source/utils/openUrl.ts b/Source/utils/openUrl.ts index 0be3f5bbb..5c7deaca7 100644 --- a/Source/utils/openUrl.ts +++ b/Source/utils/openUrl.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as open from 'open'; +import * as open from "open"; export async function openUrl(url: string): Promise { - // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 - // await vscode.env.openExternal(vscode.Uri.parse(url)); + // Using this functionality is blocked by https://github.com/Microsoft/vscode/issues/85930 + // await vscode.env.openExternal(vscode.Uri.parse(url)); - await open(url); + await open(url); } diff --git a/Source/utils/randomUtils.ts b/Source/utils/randomUtils.ts index 7a313f23a..1c4856b09 100644 --- a/Source/utils/randomUtils.ts +++ b/Source/utils/randomUtils.ts @@ -6,12 +6,15 @@ import * as crypto from "crypto"; export namespace randomUtils { - export function getPseudononymousStringHash(s: string, encoding: crypto.BinaryToTextEncoding = 'base64'): string { - return crypto.createHash('sha256').update(s).digest(encoding); - } + export function getPseudononymousStringHash( + s: string, + encoding: crypto.BinaryToTextEncoding = "base64" + ): string { + return crypto.createHash("sha256").update(s).digest(encoding); + } - export function getRandomHexString(length: number): string { - const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); - return buffer.toString('hex').slice(0, length); - } + export function getRandomHexString(length: number): string { + const buffer: Buffer = crypto.randomBytes(Math.ceil(length / 2)); + return buffer.toString("hex").slice(0, length); + } } diff --git a/Source/utils/settingUtils.ts b/Source/utils/settingUtils.ts index 0ac1004c2..0f75feb17 100644 --- a/Source/utils/settingUtils.ts +++ b/Source/utils/settingUtils.ts @@ -3,60 +3,98 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from "vscode"; +import { + ConfigurationTarget, + Uri, + workspace, + WorkspaceConfiguration, +} from "vscode"; import { ext } from "../extensionVariables"; /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateGlobalSetting(section: string, value: T, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - await projectConfiguration.update(section, value, ConfigurationTarget.Global); +export async function updateGlobalSetting( + section: string, + value: T, + prefix: string = ext.prefix +): Promise { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix); + await projectConfiguration.update( + section, + value, + ConfigurationTarget.Global + ); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export async function updateWorkspaceSetting(section: string, value: T, fsPath: string, prefix: string = ext.prefix): Promise { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, Uri.file(fsPath)); - await projectConfiguration.update(section, value); +export async function updateWorkspaceSetting( + section: string, + value: T, + fsPath: string, + prefix: string = ext.prefix +): Promise { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix, Uri.file(fsPath)); + await projectConfiguration.update(section, value); } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getGlobalSetting(key: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix); - const result: { globalValue?: T } | undefined = projectConfiguration.inspect(key); - return result && result.globalValue; +export function getGlobalSetting( + key: string, + prefix: string = ext.prefix +): T | undefined { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix); + const result: { globalValue?: T } | undefined = + projectConfiguration.inspect(key); + return result && result.globalValue; } /** * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSetting(key: string, fsPath?: string, prefix: string = ext.prefix): T | undefined { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, fsPath ? Uri.file(fsPath) : undefined); - return projectConfiguration.get(key); +export function getWorkspaceSetting( + key: string, + fsPath?: string, + prefix: string = ext.prefix +): T | undefined { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration( + prefix, + fsPath ? Uri.file(fsPath) : undefined + ); + return projectConfiguration.get(key); } /** * Searches through all open folders and gets the current workspace setting (as long as there are no conflicts) * Uses ext.prefix 'azureDatabases' unless otherwise specified */ -export function getWorkspaceSettingFromAnyFolder(key: string, prefix: string = ext.prefix): string | undefined { - if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { - let result: string | undefined; - for (const folder of workspace.workspaceFolders) { - const projectConfiguration: WorkspaceConfiguration = workspace.getConfiguration(prefix, folder.uri); - const folderResult: string | undefined = projectConfiguration.get(key); - if (!result) { - result = folderResult; - } else if (folderResult && result !== folderResult) { - return undefined; - } - } - return result; - } else { - return getGlobalSetting(key, prefix); - } +export function getWorkspaceSettingFromAnyFolder( + key: string, + prefix: string = ext.prefix +): string | undefined { + if (workspace.workspaceFolders && workspace.workspaceFolders.length > 0) { + let result: string | undefined; + for (const folder of workspace.workspaceFolders) { + const projectConfiguration: WorkspaceConfiguration = + workspace.getConfiguration(prefix, folder.uri); + const folderResult: string | undefined = + projectConfiguration.get(key); + if (!result) { + result = folderResult; + } else if (folderResult && result !== folderResult) { + return undefined; + } + } + return result; + } else { + return getGlobalSetting(key, prefix); + } } diff --git a/Source/utils/timeout.ts b/Source/utils/timeout.ts index cc5ffb2d6..1645f6d3f 100644 --- a/Source/utils/timeout.ts +++ b/Source/utils/timeout.ts @@ -8,44 +8,50 @@ const timedOutMessage = "Execution timed out"; /** * Returns the result of awaiting a specified action. Rejects if the action throws. Returns timeoutValue if a time-out occurs. */ -export async function valueOnTimeout(timeoutMs: number, timeoutValue: T, action: () => Promise | T): Promise { - try { - return await rejectOnTimeout(timeoutMs, action); - } catch (err) { - const error = <{ message?: string }>err; - if (error && error.message === timedOutMessage) { - return timeoutValue; - } +export async function valueOnTimeout( + timeoutMs: number, + timeoutValue: T, + action: () => Promise | T +): Promise { + try { + return await rejectOnTimeout(timeoutMs, action); + } catch (err) { + const error = <{ message?: string }>err; + if (error && error.message === timedOutMessage) { + return timeoutValue; + } - throw err; - } + throw err; + } } /** * Returns the result of awaiting a specified action. Rejects if the action throws or if the time-out occurs. */ -export async function rejectOnTimeout(timeoutMs: number, action: () => Promise | T, callerTimeOutMessage?: string): Promise { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - return await new Promise(async (resolve, reject) => { - let timer: NodeJS.Timer | undefined = setTimeout( - () => { - timer = undefined; - reject(new Error(callerTimeOutMessage || timedOutMessage)); - }, - timeoutMs); +export async function rejectOnTimeout( + timeoutMs: number, + action: () => Promise | T, + callerTimeOutMessage?: string +): Promise { + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + return await new Promise(async (resolve, reject) => { + let timer: NodeJS.Timer | undefined = setTimeout(() => { + timer = undefined; + reject(new Error(callerTimeOutMessage || timedOutMessage)); + }, timeoutMs); - let value: T; - let error; + let value: T; + let error; - try { - value = await action(); - clearTimeout(timer); - resolve(value); - } catch (err) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - error = err; - clearTimeout(timer); - reject(error); - } - }); + try { + value = await action(); + clearTimeout(timer); + resolve(value); + } catch (err) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + error = err; + clearTimeout(timer); + reject(error); + } + }); } diff --git a/Source/utils/vscodeUtils.ts b/Source/utils/vscodeUtils.ts index d05f84872..bdb5665b5 100644 --- a/Source/utils/vscodeUtils.ts +++ b/Source/utils/vscodeUtils.ts @@ -3,101 +3,145 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ItemDefinition } from '@azure/cosmos'; -import { AzExtTreeItem } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DocDBAccountTreeItemBase } from '../docdb/tree/DocDBAccountTreeItemBase'; -import { ext } from '../extensionVariables'; -import { MongoAccountTreeItem } from '../mongo/tree/MongoAccountTreeItem'; -import { IMongoDocument } from '../mongo/tree/MongoDocumentTreeItem'; -import { getRootPath } from './workspacUtils'; +import { ItemDefinition } from "@azure/cosmos"; +import { AzExtTreeItem } from "@microsoft/vscode-azext-utils"; +import * as fse from "fs-extra"; +import * as path from "path"; +import * as vscode from "vscode"; +import { DocDBAccountTreeItemBase } from "../docdb/tree/DocDBAccountTreeItemBase"; +import { ext } from "../extensionVariables"; +import { MongoAccountTreeItem } from "../mongo/tree/MongoAccountTreeItem"; +import { IMongoDocument } from "../mongo/tree/MongoDocumentTreeItem"; +import { getRootPath } from "./workspacUtils"; export interface IDisposable { - dispose(): void; + dispose(): void; } export function dispose(disposables: T[]): T[] { - disposables.forEach(d => d.dispose()); - return []; + disposables.forEach((d) => d.dispose()); + return []; } export function toDisposable(dispose: () => void): IDisposable { - return { dispose }; + return { dispose }; } -export async function showNewFile(data: string, fileName: string, fileExtension: string, column?: vscode.ViewColumn): Promise { - const folderPath: string = getRootPath() || ext.context.extensionPath; - const fullFileName: string | undefined = await getUniqueFileName(folderPath, fileName, fileExtension); - const uri: vscode.Uri = vscode.Uri.file(path.join(folderPath, fullFileName)).with({ scheme: 'untitled' }); - const textDocument = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(textDocument, column ? column > vscode.ViewColumn.Three ? vscode.ViewColumn.One : column : undefined, true); - await writeToEditor(editor, data); +export async function showNewFile( + data: string, + fileName: string, + fileExtension: string, + column?: vscode.ViewColumn +): Promise { + const folderPath: string = getRootPath() || ext.context.extensionPath; + const fullFileName: string | undefined = await getUniqueFileName( + folderPath, + fileName, + fileExtension + ); + const uri: vscode.Uri = vscode.Uri.file( + path.join(folderPath, fullFileName) + ).with({ scheme: "untitled" }); + const textDocument = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument( + textDocument, + column + ? column > vscode.ViewColumn.Three + ? vscode.ViewColumn.One + : column + : undefined, + true + ); + await writeToEditor(editor, data); } -export async function writeToEditor(editor: vscode.TextEditor, data: string): Promise { - await editor.edit((editBuilder: vscode.TextEditorEdit) => { - if (editor.document.lineCount > 0) { - const lastLine = editor.document.lineAt(editor.document.lineCount - 1); - editBuilder.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(lastLine.range.start.line, lastLine.range.end.character))); - } +export async function writeToEditor( + editor: vscode.TextEditor, + data: string +): Promise { + await editor.edit((editBuilder: vscode.TextEditorEdit) => { + if (editor.document.lineCount > 0) { + const lastLine = editor.document.lineAt( + editor.document.lineCount - 1 + ); + editBuilder.delete( + new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position( + lastLine.range.start.line, + lastLine.range.end.character + ) + ) + ); + } - editBuilder.insert(new vscode.Position(0, 0), data); - }); + editBuilder.insert(new vscode.Position(0, 0), data); + }); } -async function getUniqueFileName(folderPath: string, fileName: string, fileExtension: string): Promise { - let count: number = 1; - const maxCount: number = 1024; +async function getUniqueFileName( + folderPath: string, + fileName: string, + fileExtension: string +): Promise { + let count: number = 1; + const maxCount: number = 1024; - while (count < maxCount) { - const fileSuffix = count === 0 ? '' : '-' + count.toString(); - const fullFileName: string = fileName + fileSuffix + fileExtension; + while (count < maxCount) { + const fileSuffix = count === 0 ? "" : "-" + count.toString(); + const fullFileName: string = fileName + fileSuffix + fileExtension; - const fullPath: string = path.join(folderPath, fullFileName); - const pathExists: boolean = await fse.pathExists(fullPath); - const editorExists: boolean = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === fullPath) !== undefined; - if (!pathExists && !editorExists) { - return fullFileName; - } - count += 1; - } + const fullPath: string = path.join(folderPath, fullFileName); + const pathExists: boolean = await fse.pathExists(fullPath); + const editorExists: boolean = + vscode.workspace.textDocuments.find( + (doc) => doc.uri.fsPath === fullPath + ) !== undefined; + if (!pathExists && !editorExists) { + return fullFileName; + } + count += 1; + } - throw new Error('Could not find unique name for new file.'); + throw new Error("Could not find unique name for new file."); } export function getNodeEditorLabel(node: AzExtTreeItem): string { - const labels = [node.label]; - while (node.parent) { - node = node.parent; - labels.unshift(node.label); - if (isAccountTreeItem(node)) { - break; - } - } - return labels.join('/'); + const labels = [node.label]; + while (node.parent) { + node = node.parent; + labels.unshift(node.label); + if (isAccountTreeItem(node)) { + break; + } + } + return labels.join("/"); } function isAccountTreeItem(treeItem: AzExtTreeItem): boolean { - return (treeItem instanceof MongoAccountTreeItem) || (treeItem instanceof DocDBAccountTreeItemBase); + return ( + treeItem instanceof MongoAccountTreeItem || + treeItem instanceof DocDBAccountTreeItemBase + ); } -export function getDocumentTreeItemLabel(document: IMongoDocument | ItemDefinition): string { - for (const field of getDocumentLabelFields()) { - // eslint-disable-next-line no-prototype-builtins - if (document.hasOwnProperty(field)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const value = document[field]; - if (value !== undefined && typeof value !== 'object') { - return String(value); - } - } - } - return String(document._id); +export function getDocumentTreeItemLabel( + document: IMongoDocument | ItemDefinition +): string { + for (const field of getDocumentLabelFields()) { + // eslint-disable-next-line no-prototype-builtins + if (document.hasOwnProperty(field)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const value = document[field]; + if (value !== undefined && typeof value !== "object") { + return String(value); + } + } + } + return String(document._id); } function getDocumentLabelFields(): string[] { - const settingKey: string = ext.settingsKeys.documentLabelFields; - return vscode.workspace.getConfiguration().get(settingKey) || []; + const settingKey: string = ext.settingsKeys.documentLabelFields; + return vscode.workspace.getConfiguration().get(settingKey) || []; } diff --git a/Source/utils/workspacUtils.ts b/Source/utils/workspacUtils.ts index 20b60da11..6892c2f6d 100644 --- a/Source/utils/workspacUtils.ts +++ b/Source/utils/workspacUtils.ts @@ -3,16 +3,23 @@ * Licensed under the MIT License. See License.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import { ext } from '../extensionVariables'; -import { nonNullValue } from './nonNull'; +import * as vscode from "vscode"; +import { ext } from "../extensionVariables"; +import { nonNullValue } from "./nonNull"; export function getRootPath(): string | undefined { - // if this is a multi-root workspace, return undefined - return vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1 ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; + // if this is a multi-root workspace, return undefined + return vscode.workspace.workspaceFolders && + vscode.workspace.workspaceFolders.length === 1 + ? vscode.workspace.workspaceFolders[0].uri.fsPath + : undefined; } export function getBatchSizeSetting(): number { - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - return nonNullValue(config.get(ext.settingsKeys.batchSize), 'batchSize'); + const config: vscode.WorkspaceConfiguration = + vscode.workspace.getConfiguration(); + return nonNullValue( + config.get(ext.settingsKeys.batchSize), + "batchSize" + ); } diff --git a/Source/utils/wrapError.ts b/Source/utils/wrapError.ts index f6ec5d2b5..b82f638fd 100644 --- a/Source/utils/wrapError.ts +++ b/Source/utils/wrapError.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { parseError } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; +import * as os from "os"; export function wrapError(outerError?: unknown, innerError?: unknown): unknown { - if (!innerError) { - return outerError; - } else if (!outerError) { - return innerError; - } + if (!innerError) { + return outerError; + } else if (!outerError) { + return innerError; + } - const innerMessage = parseError(innerError).message; - const outerMessage = parseError(outerError).message; - if (outerError instanceof Error) { - outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; - return outerError; - } + const innerMessage = parseError(innerError).message; + const outerMessage = parseError(outerError).message; + if (outerError instanceof Error) { + outerError.message = `${outerError.message}${os.EOL}${innerMessage}`; + return outerError; + } - return new Error(`${outerMessage}${os.EOL}${innerMessage}`); + return new Error(`${outerMessage}${os.EOL}${innerMessage}`); } diff --git a/resources/icons/theme-agnostic/CosmosDBAccount.svg b/resources/icons/theme-agnostic/CosmosDBAccount.svg index e6d580065..190c8c73d 100644 --- a/resources/icons/theme-agnostic/CosmosDBAccount.svg +++ b/resources/icons/theme-agnostic/CosmosDBAccount.svg @@ -1,22 +1,35 @@ - - - - - - - - - - - Icon-databases-121 - - - - - - - - - - - + + + + + + + + + + + Icon-databases-121 + + + + + + + + + + + diff --git a/resources/icons/theme-agnostic/PostgresServer.svg b/resources/icons/theme-agnostic/PostgresServer.svg index e247e4e71..dc9b50f70 100644 --- a/resources/icons/theme-agnostic/PostgresServer.svg +++ b/resources/icons/theme-agnostic/PostgresServer.svg @@ -1 +1,27 @@ -Icon-databases-131 \ No newline at end of file + + + + + + + + + + + + + Icon-databases-131 + + + + + + From 3f3f2b621a9c58707ad088e57cd9888b9e957cad Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Fri, 24 Nov 2023 06:48:40 +0200 Subject: [PATCH 27/33] squash! --- .../IPostgresQueryWizardContext.ts | 5 +- .../IPostgresFunctionQueryWizardContext.ts | 5 +- .../function/createPostgresFunctionQuery.ts | 22 +- .../function/steps/FunctionQueryCreateStep.ts | 24 +- .../FunctionQueryCustomReturnTypeStep.ts | 19 +- .../function/steps/FunctionQueryNameStep.ts | 25 +- .../steps/FunctionQueryReturnTypeStep.ts | 87 ++-- .../runPostgresQueryWizard.ts | 29 +- .../createPostgresStoredProcedureQuery.ts | 17 +- .../steps/StoredProcedureQueryCreateStep.ts | 20 +- .../steps/StoredProcedureQueryNameStep.ts | 23 +- .../createPostgresQuery/validateIdentifier.ts | 203 ++++---- .../IPostgresServerWizardContext.ts | 34 +- .../steps/PostgresServerConfirmPWStep.ts | 40 +- .../steps/PostgresServerCreateStep.ts | 205 ++++---- .../steps/PostgresServerCredPWStep.ts | 99 ++-- .../steps/PostgresServerCredUserStep.ts | 100 ++-- .../steps/PostgresServerNameStep.ts | 143 ++++-- .../steps/PostgresServerSetCredentialsStep.ts | 84 ++-- .../steps/PostgresServerSkuStep.ts | 465 +++++++++--------- 20 files changed, 960 insertions(+), 689 deletions(-) diff --git a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts index 81d54b9af..64a4fe0b5 100644 --- a/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/IPostgresQueryWizardContext.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -7,6 +6,6 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; export interface IPostgresQueryWizardContext extends IActionContext { - name?: string; - query?: string; + name?: string; + query?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts index 27b32993c..8b4dd5f93 100644 --- a/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts +++ b/Source/postgres/commands/createPostgresQuery/function/IPostgresFunctionQueryWizardContext.ts @@ -5,6 +5,7 @@ import { IPostgresQueryWizardContext } from "../IPostgresQueryWizardContext"; -export interface IPostgresFunctionQueryWizardContext extends IPostgresQueryWizardContext { - returnType?: string; +export interface IPostgresFunctionQueryWizardContext + extends IPostgresQueryWizardContext { + returnType?: string; } diff --git a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts index 8c4df098b..ca281d4d4 100644 --- a/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/function/createPostgresFunctionQuery.ts @@ -11,13 +11,19 @@ import { FunctionQueryCreateStep } from "./steps/FunctionQueryCreateStep"; import { FunctionQueryNameStep } from "./steps/FunctionQueryNameStep"; import { FunctionQueryReturnTypeStep } from "./steps/FunctionQueryReturnTypeStep"; -export async function createPostgresFunctionQuery(context: IActionContext, treeItem?: PostgresFunctionsTreeItem): Promise { - const wizardContext: IPostgresFunctionQueryWizardContext = context; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new FunctionQueryNameStep(), new FunctionQueryReturnTypeStep()], - executeSteps: [new FunctionQueryCreateStep()], - title: 'Create PostgreSQL Function Query' - }); +export async function createPostgresFunctionQuery( + context: IActionContext, + treeItem?: PostgresFunctionsTreeItem +): Promise { + const wizardContext: IPostgresFunctionQueryWizardContext = context; + const wizard = new AzureWizard(wizardContext, { + promptSteps: [ + new FunctionQueryNameStep(), + new FunctionQueryReturnTypeStep(), + ], + executeSteps: [new FunctionQueryCreateStep()], + title: "Create PostgreSQL Function Query", + }); - await runPostgresQueryWizard(wizard, wizardContext, treeItem); + await runPostgresQueryWizard(wizard, wizardContext, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts index 9356882d9..9c0bd1e34 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCreateStep.ts @@ -9,18 +9,26 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresFunctionQueryWizardContext): Promise { - context.query = defaultFunctionQuery(nonNullProp(context, 'name'), nonNullProp(context, 'returnType')); - } + public async execute( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.query = defaultFunctionQuery( + nonNullProp(context, "name"), + nonNullProp(context, "returnType") + ); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultFunctionQuery = (name: string, returnType: string) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) +const defaultFunctionQuery = ( + name: string, + returnType: string +) => `CREATE OR REPLACE FUNCTION ${wrapArgInQuotes(name)}(/* arguments */) RETURNS ${returnType} LANGUAGE plpgsql AS $function$ diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts index cfacc0f64..a37c18995 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryCustomReturnTypeStep.ts @@ -8,11 +8,18 @@ import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryCustomReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.returnType = await context.ui.showInputBox({ prompt: localize('provideCustomReturnType', 'Provide custom return type') }); - } + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.returnType = await context.ui.showInputBox({ + prompt: localize( + "provideCustomReturnType", + "Provide custom return type" + ), + }); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts index 36d798074..78459f842 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryNameStep.ts @@ -9,14 +9,21 @@ import { validateIdentifier } from "../../validateIdentifier"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; export class FunctionQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideFunctionName', 'Provide function name'), - validateInput: validateIdentifier - })).trim(); - } + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + context.name = ( + await context.ui.showInputBox({ + prompt: localize( + "provideFunctionName", + "Provide function name" + ), + validateInput: validateIdentifier, + }) + ).trim(); + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts index 63f703793..b69c94a2c 100644 --- a/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts +++ b/Source/postgres/commands/createPostgresQuery/function/steps/FunctionQueryReturnTypeStep.ts @@ -3,48 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem, IWizardOptions } from "@microsoft/vscode-azext-utils"; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, + IWizardOptions, +} from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../../utils/localize"; import { IPostgresFunctionQueryWizardContext } from "../IPostgresFunctionQueryWizardContext"; import { FunctionQueryCustomReturnTypeStep } from "./FunctionQueryCustomReturnTypeStep"; export class FunctionQueryReturnTypeStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresFunctionQueryWizardContext): Promise { - const returnTypeQuickPicks: IAzureQuickPickItem[] = returnTypes.map(r => { return { label: r, data: r }; }); - returnTypeQuickPicks.push({ label: localize('enterCustomReturnType', '$(pencil) Enter custom return type...'), data: undefined }); + public async prompt( + context: IPostgresFunctionQueryWizardContext + ): Promise { + const returnTypeQuickPicks: IAzureQuickPickItem[] = + returnTypes.map((r) => { + return { label: r, data: r }; + }); + returnTypeQuickPicks.push({ + label: localize( + "enterCustomReturnType", + "$(pencil) Enter custom return type..." + ), + data: undefined, + }); - context.returnType = (await context.ui.showQuickPick(returnTypeQuickPicks, { - placeHolder: localize('selectReturnType', 'Select return type') - })).data; - } + context.returnType = ( + await context.ui.showQuickPick(returnTypeQuickPicks, { + placeHolder: localize("selectReturnType", "Select return type"), + }) + ).data; + } - public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { - return !context.returnType; - } + public shouldPrompt(context: IPostgresFunctionQueryWizardContext): boolean { + return !context.returnType; + } - public async getSubWizard(context: IPostgresFunctionQueryWizardContext): Promise | undefined> { - return context.returnType ? undefined : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; - } + public async getSubWizard( + context: IPostgresFunctionQueryWizardContext + ): Promise< + IWizardOptions | undefined + > { + return context.returnType + ? undefined + : { promptSteps: [new FunctionQueryCustomReturnTypeStep()] }; + } } // A subset of return types available on pgAdmin const returnTypes: string[] = [ - 'bigint', - 'bigint[]', - 'boolean', - 'boolean[]', - 'character', - 'character[]', - 'date', - 'date[]', - 'integer', - 'integer[]', - 'json', - 'json[]', - 'oid', - 'oid[]', - 'smallint', - 'smallint[]', - 'text', - 'void' + "bigint", + "bigint[]", + "boolean", + "boolean[]", + "character", + "character[]", + "date", + "date[]", + "integer", + "integer[]", + "json", + "json[]", + "oid", + "oid[]", + "smallint", + "smallint[]", + "text", + "void", ]; diff --git a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts index 925695e56..65288da3d 100644 --- a/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts +++ b/Source/postgres/commands/createPostgresQuery/runPostgresQueryWizard.ts @@ -4,20 +4,31 @@ *--------------------------------------------------------------------------------------------*/ import { AzureWizard } from "@microsoft/vscode-azext-utils"; -import { postgresBaseFileName, postgresFileExtension } from "../../../constants"; +import { + postgresBaseFileName, + postgresFileExtension, +} from "../../../constants"; import { nonNullProp } from "../../../utils/nonNull"; -import * as vscodeUtil from '../../../utils/vscodeUtils'; +import * as vscodeUtil from "../../../utils/vscodeUtils"; import { PostgresFunctionsTreeItem } from "../../tree/PostgresFunctionsTreeItem"; import { PostgresStoredProceduresTreeItem } from "../../tree/PostgresStoredProceduresTreeItem"; import { connectPostgresDatabase } from "../connectPostgresDatabase"; import { IPostgresQueryWizardContext } from "./IPostgresQueryWizardContext"; -export async function runPostgresQueryWizard(wizard: AzureWizard, context: IPostgresQueryWizardContext, treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem): Promise { - await wizard.prompt(); - await wizard.execute(); - await vscodeUtil.showNewFile(nonNullProp(context, 'query'), postgresBaseFileName, postgresFileExtension); +export async function runPostgresQueryWizard( + wizard: AzureWizard, + context: IPostgresQueryWizardContext, + treeItem?: PostgresFunctionsTreeItem | PostgresStoredProceduresTreeItem +): Promise { + await wizard.prompt(); + await wizard.execute(); + await vscodeUtil.showNewFile( + nonNullProp(context, "query"), + postgresBaseFileName, + postgresFileExtension + ); - if (treeItem) { - await connectPostgresDatabase(context, treeItem.parent); - } + if (treeItem) { + await connectPostgresDatabase(context, treeItem.parent); + } } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts index f1ddbe51b..b63bf39ae 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/createPostgresStoredProcedureQuery.ts @@ -9,12 +9,15 @@ import { runPostgresQueryWizard } from "../runPostgresQueryWizard"; import { StoredProcedureQueryCreateStep } from "./steps/StoredProcedureQueryCreateStep"; import { StoredProcedureQueryNameStep } from "./steps/StoredProcedureQueryNameStep"; -export async function createPostgresStoredProcedureQuery(context: IActionContext, treeItem?: PostgresStoredProceduresTreeItem): Promise { - const wizard = new AzureWizard(context, { - promptSteps: [new StoredProcedureQueryNameStep()], - executeSteps: [new StoredProcedureQueryCreateStep()], - title: 'Create PostgreSQL Stored Procedure Query' - }); +export async function createPostgresStoredProcedureQuery( + context: IActionContext, + treeItem?: PostgresStoredProceduresTreeItem +): Promise { + const wizard = new AzureWizard(context, { + promptSteps: [new StoredProcedureQueryNameStep()], + executeSteps: [new StoredProcedureQueryCreateStep()], + title: "Create PostgreSQL Stored Procedure Query", + }); - await runPostgresQueryWizard(wizard, context, treeItem); + await runPostgresQueryWizard(wizard, context, treeItem); } diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts index 2cf3ef916..67bbbbf0c 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryCreateStep.ts @@ -9,18 +9,22 @@ import { wrapArgInQuotes } from "../../../../runPostgresQuery"; import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; export class StoredProcedureQueryCreateStep extends AzureWizardExecuteStep { - public priority: number = 100; + public priority: number = 100; - public async execute(context: IPostgresQueryWizardContext): Promise { - context.query = defaultStoredProcedureQuery(nonNullProp(context, 'name')); - } + public async execute(context: IPostgresQueryWizardContext): Promise { + context.query = defaultStoredProcedureQuery( + nonNullProp(context, "name") + ); + } - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } -const defaultStoredProcedureQuery = (name: string) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) +const defaultStoredProcedureQuery = ( + name: string +) => `CREATE OR REPLACE PROCEDURE ${wrapArgInQuotes(name)}(/* arguments */) LANGUAGE plpgsql AS $$ BEGIN diff --git a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts index bf9a00392..5b694f378 100644 --- a/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts +++ b/Source/postgres/commands/createPostgresQuery/storedProcedure/steps/StoredProcedureQueryNameStep.ts @@ -9,14 +9,19 @@ import { IPostgresQueryWizardContext } from "../../IPostgresQueryWizardContext"; import { validateIdentifier } from "../../validateIdentifier"; export class StoredProcedureQueryNameStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresQueryWizardContext): Promise { - context.name = (await context.ui.showInputBox({ - prompt: localize('provideStoredProcedureName', 'Provide stored procedure name'), - validateInput: validateIdentifier - })).trim(); - } + public async prompt(context: IPostgresQueryWizardContext): Promise { + context.name = ( + await context.ui.showInputBox({ + prompt: localize( + "provideStoredProcedureName", + "Provide stored procedure name" + ), + validateInput: validateIdentifier, + }) + ).trim(); + } - public shouldPrompt(context: IPostgresQueryWizardContext): boolean { - return !context.name; - } + public shouldPrompt(context: IPostgresQueryWizardContext): boolean { + return !context.name; + } } diff --git a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts index 9339f6796..94bb16657 100644 --- a/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts +++ b/Source/postgres/commands/createPostgresQuery/validateIdentifier.ts @@ -6,108 +6,123 @@ import { localize } from "../../../utils/localize"; export function validateIdentifier(identifier: string): string | undefined { - // Identifier naming rules: https://aka.ms/AA8618j - identifier = identifier.trim(); + // Identifier naming rules: https://aka.ms/AA8618j + identifier = identifier.trim(); - const min = 1; - const max = 63; + const min = 1; + const max = 63; - if (identifier.length < min || identifier.length > max) { - return localize('postgresResourcesNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } + if (identifier.length < min || identifier.length > max) { + return localize( + "postgresResourcesNameLengthCheck", + "The name must be between {0} and {1} characters.", + min, + max + ); + } - if (!identifier[0].match(/[a-z_]/i)) { - return localize('mustStartWithLetterOrUnderscore', 'Name must start with a letter or underscore.'); - } + if (!identifier[0].match(/[a-z_]/i)) { + return localize( + "mustStartWithLetterOrUnderscore", + "Name must start with a letter or underscore." + ); + } - if (identifier.match(/[^a-z_\d$]/i)) { - return localize('canOnlyContainCertainCharacters', 'Name can only contain letters, underscores, digits (0-9), and dollar signs ($).'); - } + if (identifier.match(/[^a-z_\d$]/i)) { + return localize( + "canOnlyContainCertainCharacters", + "Name can only contain letters, underscores, digits (0-9), and dollar signs ($)." + ); + } - if (reservedWords.has(identifier.toLowerCase())) { - return localize('cantBeReservedWord', 'Name cannot be reserved word "{0}".', identifier); - } + if (reservedWords.has(identifier.toLowerCase())) { + return localize( + "cantBeReservedWord", + 'Name cannot be reserved word "{0}".', + identifier + ); + } - return undefined; + return undefined; } // Key words that are reserved in PostgreSQL. Source: https://www.postgresql.org/docs/10/sql-keywords-appendix.html const reservedWords: Set = new Set([ - 'all', - 'analyse', - 'analyze', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'asymmetric', - 'both', - 'case', - 'cast', - 'check', - 'collate', - 'column', - 'constraint', - 'create', - 'current_catalog', - 'current_date', - 'current_role', - 'current_time', - 'current_timestamp', - 'current_user', - 'default', - 'deferrable', - 'desc', - 'distinct', - 'do', - 'else', - 'end', - 'except', - 'false', - 'fetch', - 'for', - 'foreign', - 'from', - 'grant', - 'group', - 'having', - 'in', - 'initially', - 'intersect', - 'into', - 'lateral', - 'leading', - 'limit', - 'localtime', - 'localtimestamp', - 'not', - 'null', - 'offset', - 'on', - 'only', - 'or', - 'order', - 'placing', - 'primary', - 'references', - 'returning', - 'select', - 'session_user', - 'some', - 'symmetric', - 'table', - 'then', - 'to', - 'trailing', - 'true', - 'union', - 'unique', - 'user', - 'using', - 'variadic', - 'when', - 'where', - 'window', - 'with' + "all", + "analyse", + "analyze", + "and", + "any", + "array", + "as", + "asc", + "asymmetric", + "both", + "case", + "cast", + "check", + "collate", + "column", + "constraint", + "create", + "current_catalog", + "current_date", + "current_role", + "current_time", + "current_timestamp", + "current_user", + "default", + "deferrable", + "desc", + "distinct", + "do", + "else", + "end", + "except", + "false", + "fetch", + "for", + "foreign", + "from", + "grant", + "group", + "having", + "in", + "initially", + "intersect", + "into", + "lateral", + "leading", + "limit", + "localtime", + "localtimestamp", + "not", + "null", + "offset", + "on", + "only", + "or", + "order", + "placing", + "primary", + "references", + "returning", + "select", + "session_user", + "some", + "symmetric", + "table", + "then", + "to", + "trailing", + "true", + "union", + "unique", + "user", + "using", + "variadic", + "when", + "where", + "window", + "with", ]); diff --git a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts index 390c1cf42..cc28cd581 100644 --- a/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts +++ b/Source/postgres/commands/createPostgresServer/IPostgresServerWizardContext.ts @@ -5,20 +5,26 @@ import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; import { IAzureDBWizardContext } from "../../../tree/IAzureDBWizardContext"; -import { AbstractSku, PostgresAbstractServer, PostgresServerType } from "../../abstract/models"; +import { + AbstractSku, + PostgresAbstractServer, + PostgresServerType, +} from "../../abstract/models"; -export interface IPostgresServerWizardContext extends IAzureDBWizardContext, ExecuteActivityContext { - /** - * Username without server, i.e. "user1" - */ - shortUserName?: string; - /** - * Username with server, i.e. "user1@server1" - */ - longUserName?: string; - adminPassword?: string; +export interface IPostgresServerWizardContext + extends IAzureDBWizardContext, + ExecuteActivityContext { + /** + * Username without server, i.e. "user1" + */ + shortUserName?: string; + /** + * Username with server, i.e. "user1@server1" + */ + longUserName?: string; + adminPassword?: string; - server?: PostgresAbstractServer; - sku?: AbstractSku; - serverType?: PostgresServerType; + server?: PostgresAbstractServer; + sku?: AbstractSku; + serverType?: PostgresServerType; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts index 2f07d8203..20d13ffbf 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerConfirmPWStep.ts @@ -8,24 +8,30 @@ import { localize } from "../../../../utils/localize"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerConfirmPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const prompt: string = localize('confirmPW', 'Confirm your password'); - await context.ui.showInputBox({ - prompt, - password: true, - validateInput: async (value: string | undefined): Promise => await this.validatePassword(context, value) - }); - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const prompt: string = localize("confirmPW", "Confirm your password"); + await context.ui.showInputBox({ + prompt, + password: true, + validateInput: async ( + value: string | undefined + ): Promise => + await this.validatePassword(context, value), + }); + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !!context.adminPassword; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !!context.adminPassword; + } - private async validatePassword(context: IPostgresServerWizardContext, passphrase: string | undefined): Promise { - if (passphrase !== context.adminPassword) { - return localize('pwMatch', 'The passwords must match.'); - } + private async validatePassword( + context: IPostgresServerWizardContext, + passphrase: string | undefined + ): Promise { + if (passphrase !== context.adminPassword) { + return localize("pwMatch", "The passwords must match."); + } - return undefined; - } + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts index f73ce810d..549f1e67f 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCreateStep.ts @@ -5,100 +5,133 @@ import * as SingleModels from "@azure/arm-postgresql"; import * as FlexibleModels from "@azure/arm-postgresql-flexible"; import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, callWithMaskHandling } from '@microsoft/vscode-azext-utils'; +import { + AzureWizardExecuteStep, + callWithMaskHandling, +} from "@microsoft/vscode-azext-utils"; import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { createPostgreSQLClient, createPostgreSQLFlexibleClient } from "../../../../utils/azureClients"; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractServerCreate, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { Progress } from "vscode"; +import { ext } from "../../../../extensionVariables"; +import { + createPostgreSQLClient, + createPostgreSQLFlexibleClient, +} from "../../../../utils/azureClients"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + AbstractServerCreate, + PostgresServerType, +} from "../../../abstract/models"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerCreateStep extends AzureWizardExecuteStep { - public priority: number = 150; + public priority: number = 150; - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + public async execute( + context: IPostgresServerWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + const locationName: string = ( + await LocationListStep.getLocation(context) + ).name; + const rgName: string = nonNullProp( + nonNullProp(context, "resourceGroup"), + "name" + ); + const size: string = nonNullProp(nonNullProp(context, "sku"), "size"); + const newServerName = nonNullProp(context, "newServerName"); + const password: string = nonNullProp(context, "adminPassword"); - const locationName: string = (await LocationListStep.getLocation(context)).name; - const rgName: string = nonNullProp(nonNullProp(context, 'resourceGroup'), 'name'); - const size: string = nonNullProp(nonNullProp(context, 'sku'), 'size'); - const newServerName = nonNullProp(context, 'newServerName'); - const password: string = nonNullProp(context, 'adminPassword'); + return await callWithMaskHandling(async () => { + const serverType = nonNullProp(context, "serverType"); + const createMessage: string = localize( + "creatingPostgresServer", + 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', + context.newServerName + ); - return await callWithMaskHandling( - async () => { - const serverType = nonNullProp(context, 'serverType'); - const createMessage: string = localize('creatingPostgresServer', 'Creating PostgreSQL Server "{0}"... It should be ready in several minutes.', context.newServerName); + ext.outputChannel.appendLog(createMessage); + progress.report({ message: createMessage }); + const options: AbstractServerCreate = { + location: locationName, + sku: nonNullProp(context, "sku"), + administratorLogin: nonNullProp(context, "shortUserName"), + administratorLoginPassword: password, + size: parseInt(size), + }; - ext.outputChannel.appendLog(createMessage); - progress.report({ message: createMessage }); - const options: AbstractServerCreate = { - location: locationName, - sku: nonNullProp(context, 'sku'), - administratorLogin: nonNullProp(context, 'shortUserName'), - administratorLoginPassword: password, - size: parseInt(size) - }; + switch (serverType) { + case PostgresServerType.Single: + const singleClient: SingleModels.PostgreSQLManagementClient = + await createPostgreSQLClient(context); + context.server = + await singleClient.servers.beginCreateAndWait( + rgName, + newServerName, + this.asSingleParameters(options) + ); + break; + case PostgresServerType.Flexible: + const flexiClient: FlexibleModels.PostgreSQLManagementClient = + await createPostgreSQLFlexibleClient(context); + context.server = + await flexiClient.servers.beginCreateAndWait( + rgName, + newServerName, + this.asFlexibleParameters(options) + ); + break; + } + context.server.serverType = serverType; + context.activityResult = context.server as AppResource; + }, password); + } - switch (serverType) { - case PostgresServerType.Single: - const singleClient: SingleModels.PostgreSQLManagementClient = await createPostgreSQLClient(context); - context.server = await singleClient.servers.beginCreateAndWait(rgName, newServerName, this.asSingleParameters(options)); - break; - case PostgresServerType.Flexible: - const flexiClient: FlexibleModels.PostgreSQLManagementClient = await createPostgreSQLFlexibleClient(context); - context.server = await flexiClient.servers.beginCreateAndWait(rgName, newServerName, this.asFlexibleParameters(options)); - break; - } - context.server.serverType = serverType; - context.activityResult = context.server as AppResource; - }, - password); - } + public shouldExecute(context: IPostgresServerWizardContext): boolean { + return !context.server; + } - public shouldExecute(context: IPostgresServerWizardContext): boolean { - return !context.server; - } - - - private asFlexibleParameters(parameters: AbstractServerCreate): FlexibleModels.Server { - return { - location: parameters.location, - version: "12", - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - storage: { - storageSizeGB: parameters.size - }, - sku: { - name: parameters.sku.name, - tier: parameters.sku.tier - }, - } - } - - private asSingleParameters(parameters: AbstractServerCreate): SingleModels.ServerForCreate { - return { - location: parameters.location, - sku: { - name: parameters.sku.name, - capacity: parameters.sku.capacity, - size: parameters.sku.size, - family: parameters.sku.family, - tier: parameters.sku.tier as SingleModels.SkuTier - }, - properties: { - administratorLogin: parameters.administratorLogin, - administratorLoginPassword: parameters.administratorLoginPassword, - sslEnforcement: "Enabled", - createMode: "Default", - version: "11", - storageProfile: { - storageMB: parameters.size - } - } - } - } + private asFlexibleParameters( + parameters: AbstractServerCreate + ): FlexibleModels.Server { + return { + location: parameters.location, + version: "12", + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: parameters.administratorLoginPassword, + storage: { + storageSizeGB: parameters.size, + }, + sku: { + name: parameters.sku.name, + tier: parameters.sku.tier, + }, + }; + } + private asSingleParameters( + parameters: AbstractServerCreate + ): SingleModels.ServerForCreate { + return { + location: parameters.location, + sku: { + name: parameters.sku.name, + capacity: parameters.sku.capacity, + size: parameters.sku.size, + family: parameters.sku.family, + tier: parameters.sku.tier as SingleModels.SkuTier, + }, + properties: { + administratorLogin: parameters.administratorLogin, + administratorLoginPassword: + parameters.administratorLoginPassword, + sslEnforcement: "Enabled", + createMode: "Default", + version: "11", + storageProfile: { + storageMB: parameters.size, + }, + }, + }; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts index c48d40c37..dd5c84c25 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredPWStep.ts @@ -3,51 +3,66 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; -const pwConditionMsg = localize('passwordConditionMsg', 'Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.).'); +const pwConditionMsg = localize( + "passwordConditionMsg", + "Password must contain characters from three of the following categories - uppercase letters, lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, etc.)." +); export class PostgresServerCredPWStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - const user = nonNullProp(context, 'shortUserName'); - context.adminPassword = (await context.ui.showInputBox({ - placeHolder: localize('pwPlaceholder', 'Administrator Password'), - prompt: pwConditionMsg, - password: true, - validateInput: (password: string) => validatePassword(user, password), - })); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.adminPassword; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + const user = nonNullProp(context, "shortUserName"); + context.adminPassword = await context.ui.showInputBox({ + placeHolder: localize("pwPlaceholder", "Administrator Password"), + prompt: pwConditionMsg, + password: true, + validateInput: (password: string) => + validatePassword(user, password), + }); + } + + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.adminPassword; + } } -async function validatePassword(username: string, password: string): Promise { - password = password ? password : ''; - - const min = 8; - const max = 128; - - const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; - let numOccurrence = 0; - - regex.map(substring => { - if (password.match(substring)) { - numOccurrence++; - } - }); - - if (password.length < min || password.length > max) { - return localize('pwLengthCheck', 'Password must be between {0} and {1} characters.', min, max); - } else if (numOccurrence < 3) { - return pwConditionMsg; - } else if (password.includes(username)) { - return localize('pwUserSimalarityCheck', 'Password cannot contain the username.'); - } else { - return undefined; - } +async function validatePassword( + username: string, + password: string +): Promise { + password = password ? password : ""; + + const min = 8; + const max = 128; + + const regex = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^a-zA-Z\d\s]/]; + let numOccurrence = 0; + + regex.map((substring) => { + if (password.match(substring)) { + numOccurrence++; + } + }); + + if (password.length < min || password.length > max) { + return localize( + "pwLengthCheck", + "Password must be between {0} and {1} characters.", + min, + max + ); + } else if (numOccurrence < 3) { + return pwConditionMsg; + } else if (password.includes(username)) { + return localize( + "pwUserSimalarityCheck", + "Password cannot contain the username." + ); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts index 7b4890d07..14b7de8f7 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerCredUserStep.ts @@ -3,46 +3,80 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerCredUserStep extends AzureWizardPromptStep { - public async prompt(context: IPostgresServerWizardContext): Promise { - context.shortUserName = (await context.ui.showInputBox({ - placeHolder: localize('usernamePlaceholder', 'Administrator Username'), - validateInput: validateUser, - })).trim(); - const usernameSuffix: string = `@${nonNullProp(context, 'newServerName')}`; - context.longUserName = context.shortUserName + usernameSuffix; - } + public async prompt(context: IPostgresServerWizardContext): Promise { + context.shortUserName = ( + await context.ui.showInputBox({ + placeHolder: localize( + "usernamePlaceholder", + "Administrator Username" + ), + validateInput: validateUser, + }) + ).trim(); + const usernameSuffix: string = `@${nonNullProp( + context, + "newServerName" + )}`; + context.longUserName = context.shortUserName + usernameSuffix; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.shortUserName; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.shortUserName; + } } async function validateUser(username: string): Promise { - username = username ? username.trim() : ''; + username = username ? username.trim() : ""; - const min = 1; - const max = 63; + const min = 1; + const max = 63; - const restricted = ['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public']; + const restricted = [ + "azure_superuser", + "azure_pg_admin", + "admin", + "administrator", + "root", + "guest", + "public", + ]; - if (username.length < min || username.length > max) { - return localize('usernameLenghtMatch', 'The name must be between {0} and {1} characters.', min, max); - } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { - return localize('usernameCharacterCheck', 'The name can only contain letters, numbers, and the "_" character.'); - } else if (username.match(/^[0-9]+/)) { - return localize('usernameBeginningMatch', 'The name cannot start with a number.'); - } else if (username.toLowerCase().startsWith('pg_')) { - return localize('usernameStartWithCheck', 'Admin username cannot start with "pg_".'); - } else if (restricted.includes(username.toLowerCase())) { - const restrictedString = restricted.map(d => `"${d}"`).join(', '); - return localize('usernameRestrictedCheck', 'Admin username cannot be any of the following: {0}.', restrictedString); - } else { - return undefined; - } + if (username.length < min || username.length > max) { + return localize( + "usernameLenghtMatch", + "The name must be between {0} and {1} characters.", + min, + max + ); + } else if (!username.match(/^[a-zA-Z0-9_]+$/)) { + return localize( + "usernameCharacterCheck", + 'The name can only contain letters, numbers, and the "_" character.' + ); + } else if (username.match(/^[0-9]+/)) { + return localize( + "usernameBeginningMatch", + "The name cannot start with a number." + ); + } else if (username.toLowerCase().startsWith("pg_")) { + return localize( + "usernameStartWithCheck", + 'Admin username cannot start with "pg_".' + ); + } else if (restricted.includes(username.toLowerCase())) { + const restrictedString = restricted.map((d) => `"${d}"`).join(", "); + return localize( + "usernameRestrictedCheck", + "Admin username cannot be any of the following: {0}.", + restrictedString + ); + } else { + return undefined; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts index 1af03f5c7..76b25373e 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerNameStep.ts @@ -3,58 +3,111 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ResourceGroupListStep, resourceGroupNamingRules } from '@microsoft/vscode-azext-azureutils'; -import { AzureNameStep } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { AbstractPostgresClient, createAbstractPostgresClient } from '../../../abstract/AbstractPostgresClient'; -import { AbstractNameAvailability, PostgresServerType } from '../../../abstract/models'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { + ResourceGroupListStep, + resourceGroupNamingRules, +} from "@microsoft/vscode-azext-azureutils"; +import { AzureNameStep } from "@microsoft/vscode-azext-utils"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + AbstractPostgresClient, + createAbstractPostgresClient, +} from "../../../abstract/AbstractPostgresClient"; +import { + AbstractNameAvailability, + PostgresServerType, +} from "../../../abstract/models"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerNameStep extends AzureNameStep { + public async prompt(context: IPostgresServerWizardContext): Promise { + const client = await createAbstractPostgresClient( + nonNullProp(context, "serverType"), + context + ); + context.newServerName = ( + await context.ui.showInputBox({ + placeHolder: localize("serverNamePlaceholder", "Server name"), + prompt: localize( + "enterServerNamePrompt", + "Provide a name for the PostgreSQL Server." + ), + validateInput: (name: string) => + validatePostgresServerName( + name, + client, + nonNullProp(context, "serverType") + ), + }) + ).trim(); + context.valuesToMask.push(context.newServerName); + context.relatedNameTask = this.generateRelatedName( + context, + context.newServerName, + resourceGroupNamingRules + ); + } - public async prompt(context: IPostgresServerWizardContext): Promise { - const client = await createAbstractPostgresClient(nonNullProp(context, "serverType"), context); - context.newServerName = (await context.ui.showInputBox({ - placeHolder: localize('serverNamePlaceholder', 'Server name'), - prompt: localize('enterServerNamePrompt', 'Provide a name for the PostgreSQL Server.'), - validateInput: (name: string) => validatePostgresServerName(name, client, nonNullProp(context, "serverType")) - })).trim(); - context.valuesToMask.push(context.newServerName); - context.relatedNameTask = this.generateRelatedName(context, context.newServerName, resourceGroupNamingRules); - } - - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return !context.newServerName; - } - - protected async isRelatedNameAvailable(context: IPostgresServerWizardContext, name: string): Promise { - return await ResourceGroupListStep.isNameAvailable(context, name); - } -} + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return !context.newServerName; + } -async function validatePostgresServerName(name: string, client: AbstractPostgresClient, serverType: PostgresServerType): Promise { - name = name ? name.trim() : ''; + protected async isRelatedNameAvailable( + context: IPostgresServerWizardContext, + name: string + ): Promise { + return await ResourceGroupListStep.isNameAvailable(context, name); + } +} - const min = 3; - const max = 63; +async function validatePostgresServerName( + name: string, + client: AbstractPostgresClient, + serverType: PostgresServerType +): Promise { + name = name ? name.trim() : ""; - if (name.length < min || name.length > max) { - return localize('serverNameLengthCheck', 'The name must be between {0} and {1} characters.', min, max); - } else if (!(/^[a-z0-9-]+$/).test(name)) { - return localize('serverNameCharacterCheck', 'Server name must only contain lowercase letters, numbers, and hyphens.'); - } else if (name.startsWith('-') || name.endsWith('-')) { - return localize('serverNamePrefixSuffixCheck', 'Server name must not start or end in a hyphen.'); - } - const resourceType = serverType === PostgresServerType.Single ? "Microsoft.DBforPostgreSQL" : "Microsoft.DBforPostgreSQL/flexibleServers"; - const availability: AbstractNameAvailability = await client.checkNameAvailability.execute({ name: name, type: resourceType }); + const min = 3; + const max = 63; - if (!availability.nameAvailable) { - return availability.message ? - availability.message : - localize('serverNameAvailabilityCheck', 'Server name "{0}" is not available.', name); - } + if (name.length < min || name.length > max) { + return localize( + "serverNameLengthCheck", + "The name must be between {0} and {1} characters.", + min, + max + ); + } else if (!/^[a-z0-9-]+$/.test(name)) { + return localize( + "serverNameCharacterCheck", + "Server name must only contain lowercase letters, numbers, and hyphens." + ); + } else if (name.startsWith("-") || name.endsWith("-")) { + return localize( + "serverNamePrefixSuffixCheck", + "Server name must not start or end in a hyphen." + ); + } + const resourceType = + serverType === PostgresServerType.Single + ? "Microsoft.DBforPostgreSQL" + : "Microsoft.DBforPostgreSQL/flexibleServers"; + const availability: AbstractNameAvailability = + await client.checkNameAvailability.execute({ + name: name, + type: resourceType, + }); - return undefined; + if (!availability.nameAvailable) { + return availability.message + ? availability.message + : localize( + "serverNameAvailabilityCheck", + 'Server name "{0}" is not available.', + name + ); + } + return undefined; } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts index 3431e8f00..e93027936 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSetCredentialsStep.ts @@ -3,44 +3,60 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { Progress } from 'vscode'; -import { ext } from '../../../../extensionVariables'; -import { localize } from '../../../../utils/localize'; -import { nonNullProp } from '../../../../utils/nonNull'; -import { PostgresAbstractServer, PostgresServerType } from '../../../abstract/models'; -import { setPostgresCredentials } from '../../setPostgresCredentials'; -import { IPostgresServerWizardContext } from '../IPostgresServerWizardContext'; +import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils"; +import * as vscode from "vscode"; +import { Progress } from "vscode"; +import { ext } from "../../../../extensionVariables"; +import { localize } from "../../../../utils/localize"; +import { nonNullProp } from "../../../../utils/nonNull"; +import { + PostgresAbstractServer, + PostgresServerType, +} from "../../../abstract/models"; +import { setPostgresCredentials } from "../../setPostgresCredentials"; +import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; export class PostgresServerSetCredentialsStep extends AzureWizardExecuteStep { - public priority: number = 200; + public priority: number = 200; - public async execute(context: IPostgresServerWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise { + public async execute( + context: IPostgresServerWizardContext, + progress: Progress<{ message?: string; increment?: number }> + ): Promise { + let user: string; + // Username doesn't contain servername prefix for Postgres Flexible Servers only + // As present on the portal for any Flexbile Server instance + if ( + context.serverType && + context.serverType === PostgresServerType.Single + ) { + user = nonNullProp(context, "longUserName"); + } else { + user = nonNullProp(context, "shortUserName"); + } + const newServerName: string = nonNullProp(context, "newServerName"); - let user: string; - // Username doesn't contain servername prefix for Postgres Flexible Servers only - // As present on the portal for any Flexbile Server instance - if (context.serverType && context.serverType === PostgresServerType.Single) { - user = nonNullProp(context, 'longUserName'); - } else { - user = nonNullProp(context, 'shortUserName'); - } - const newServerName: string = nonNullProp(context, 'newServerName'); + const setupMessage: string = localize( + "setupCredentialsMessage", + 'Setting up Credentials for server "{0}"...', + newServerName + ); + progress.report({ message: setupMessage }); + ext.outputChannel.appendLog(setupMessage); + const password: string = nonNullProp(context, "adminPassword"); + const server: PostgresAbstractServer = nonNullProp(context, "server"); - const setupMessage: string = localize('setupCredentialsMessage', 'Setting up Credentials for server "{0}"...', newServerName); - progress.report({ message: setupMessage }); - ext.outputChannel.appendLog(setupMessage); - const password: string = nonNullProp(context, 'adminPassword'); - const server: PostgresAbstractServer = nonNullProp(context, 'server'); + await setPostgresCredentials(user, password, nonNullProp(server, "id")); + const completedMessage: string = localize( + "addedCredentialsMessage", + 'Successfully setup credentials for server "{0}".', + newServerName + ); + void vscode.window.showInformationMessage(completedMessage); + ext.outputChannel.appendLog(completedMessage); + } - await setPostgresCredentials(user, password, nonNullProp(server, 'id')); - const completedMessage: string = localize('addedCredentialsMessage', 'Successfully setup credentials for server "{0}".', newServerName); - void vscode.window.showInformationMessage(completedMessage); - ext.outputChannel.appendLog(completedMessage); - } - - public shouldExecute(): boolean { - return true; - } + public shouldExecute(): boolean { + return true; + } } diff --git a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts index 654cd0430..3efe5e223 100644 --- a/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts +++ b/Source/postgres/commands/createPostgresServer/steps/PostgresServerSkuStep.ts @@ -2,7 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils"; +import { + AzureWizardPromptStep, + IAzureQuickPickItem, +} from "@microsoft/vscode-azext-utils"; import { localize } from "../../../../utils/localize"; import { nonNullProp } from "../../../../utils/nonNull"; import { openUrl } from "../../../../utils/openUrl"; @@ -10,241 +13,257 @@ import { AbstractSku, PostgresServerType } from "../../../abstract/models"; import { IPostgresServerWizardContext } from "../IPostgresServerWizardContext"; interface ISkuOption { - label: string; - description: string; - sku: AbstractSku; - group?: string; + label: string; + description: string; + sku: AbstractSku; + group?: string; } export class PostgresServerSkuStep extends AzureWizardPromptStep { - public async prompt( - context: IPostgresServerWizardContext - ): Promise { - const placeHolder: string = localize( - "selectPostgresSku", - "Select the Postgres SKU and options." - ); - const pricingTiers: IAzureQuickPickItem[] = await this.getPicks(nonNullProp(context, 'serverType')); - pricingTiers.push({ - label: localize('ShowPricingCalculator', '$(link-external) Show pricing information...'), - onPicked: async () => { - await openUrl('https://aka.ms/AAcxhvm'); - }, data: undefined - }); + public async prompt(context: IPostgresServerWizardContext): Promise { + const placeHolder: string = localize( + "selectPostgresSku", + "Select the Postgres SKU and options." + ); + const pricingTiers: IAzureQuickPickItem[] = + await this.getPicks(nonNullProp(context, "serverType")); + pricingTiers.push({ + label: localize( + "ShowPricingCalculator", + "$(link-external) Show pricing information..." + ), + onPicked: async () => { + await openUrl("https://aka.ms/AAcxhvm"); + }, + data: undefined, + }); - context.sku = (await context.ui.showQuickPick(pricingTiers, { placeHolder, suppressPersistence: true, enableGrouping: true })).data; - } + context.sku = ( + await context.ui.showQuickPick(pricingTiers, { + placeHolder, + suppressPersistence: true, + enableGrouping: true, + }) + ).data; + } - public shouldPrompt(context: IPostgresServerWizardContext): boolean { - return context.sku === undefined; - } + public shouldPrompt(context: IPostgresServerWizardContext): boolean { + return context.sku === undefined; + } - public async getPicks(serverType: PostgresServerType): Promise[]> { - const options: IAzureQuickPickItem[] = []; - const skuOptions: ISkuOption[] = serverType === PostgresServerType.Single ? singleServerSkus : flexibleServerSkus; + public async getPicks( + serverType: PostgresServerType + ): Promise[]> { + const options: IAzureQuickPickItem[] = []; + const skuOptions: ISkuOption[] = + serverType === PostgresServerType.Single + ? singleServerSkus + : flexibleServerSkus; - skuOptions.forEach((option) => { - options.push({ - label: option.label, - description: localize( - nonNullProp(option.sku, "name"), - option.description - ), - data: option.sku, - group: option.group || localize('addlOptions', 'Additional Options') - }); - }); - return options; - } + skuOptions.forEach((option) => { + options.push({ + label: option.label, + description: localize( + nonNullProp(option.sku, "name"), + option.description + ), + data: option.sku, + group: + option.group || + localize("addlOptions", "Additional Options"), + }); + }); + return options; + } } -const recommendedGroup = localize('recommendGroup', 'Recommended'); +const recommendedGroup = localize("recommendGroup", "Recommended"); const singleServerSkus: ISkuOption[] = [ - { - label: "B1", - description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", - sku: { - name: "B_Gen5_1", - tier: "Basic", - capacity: 1, - family: "Gen5", - size: "5120", - }, - group: recommendedGroup - }, - { - label: "B2", - description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", - sku: { - name: "B_Gen5_2", - tier: "Basic", - capacity: 2, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP2", - description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_2", - tier: "GeneralPurpose", - capacity: 2, - family: "Gen5", - size: "51200", - }, - group: recommendedGroup - }, - { - label: "GP4", - description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", - sku: { - name: "GP_Gen5_4", - tier: "GeneralPurpose", - capacity: 4, - family: "Gen5", - size: "51200", - }, - }, - { - label: "GP8", - description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_8", - tier: "GeneralPurpose", - capacity: 8, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP16", - description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_16", - tier: "GeneralPurpose", - capacity: 16, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP32", - description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_32", - tier: "GeneralPurpose", - capacity: 32, - family: "Gen5", - size: "204800", - }, - }, - { - label: "GP64", - description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", - sku: { - name: "GP_Gen5_64", - tier: "GeneralPurpose", - capacity: 64, - family: "Gen5", - size: "204800", - }, - }, + { + label: "B1", + description: "Basic, 1 vCore, 2GiB Memory, 5GB storage", + sku: { + name: "B_Gen5_1", + tier: "Basic", + capacity: 1, + family: "Gen5", + size: "5120", + }, + group: recommendedGroup, + }, + { + label: "B2", + description: "Basic, 2 vCores, 4GiB Memory, 50GB storage", + sku: { + name: "B_Gen5_2", + tier: "Basic", + capacity: 2, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP2", + description: "General Purpose, 2 vCores, 10GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_2", + tier: "GeneralPurpose", + capacity: 2, + family: "Gen5", + size: "51200", + }, + group: recommendedGroup, + }, + { + label: "GP4", + description: "General Purpose, 4 vCores, 20GiB Memory, 50GB storage", + sku: { + name: "GP_Gen5_4", + tier: "GeneralPurpose", + capacity: 4, + family: "Gen5", + size: "51200", + }, + }, + { + label: "GP8", + description: "General Purpose, 8 vCores, 40GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_8", + tier: "GeneralPurpose", + capacity: 8, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP16", + description: "General Purpose, 16 vCores, 80GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_16", + tier: "GeneralPurpose", + capacity: 16, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP32", + description: "General Purpose, 32 vCores, 160GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_32", + tier: "GeneralPurpose", + capacity: 32, + family: "Gen5", + size: "204800", + }, + }, + { + label: "GP64", + description: "General Purpose, 64 vCores, 320GiB Memory, 200GB storage", + sku: { + name: "GP_Gen5_64", + tier: "GeneralPurpose", + capacity: 64, + family: "Gen5", + size: "204800", + }, + }, ]; // Official storage sizes are 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 // See https://docs.microsoft.com/en-au/azure/postgresql/flexible-server/concepts-compute-storage#storage const flexibleServerSkus: ISkuOption[] = [ - { - label: "B1ms", - description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", - sku: { - name: "Standard_B1ms", - tier: "Burstable", - capacity: 1, - size: "32", - }, - group: recommendedGroup - }, - { - label: "B2s", - description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", - sku: { - name: "Standard_B2s", - tier: "Burstable", - capacity: 2, - size: "32", - }, - }, - { - label: "D2s_v3", - description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", - sku: { - name: "Standard_D2s_v3", - tier: "GeneralPurpose", - capacity: 2, - size: "32", - }, - group: recommendedGroup - }, - { - label: "D4s_v3", - description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", - sku: { - name: "Standard_D4s_v3", - tier: "GeneralPurpose", - capacity: 4, - size: "32", - }, - }, - { - label: "D8s_v3", - description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", - sku: { - name: "Standard_D8s_v3", - tier: "GeneralPurpose", - capacity: 8, - size: "64", - }, - }, - { - label: "D16s_v3", - description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", - sku: { - name: "Standard_D16s_v3", - tier: "GeneralPurpose", - capacity: 16, - size: "64", - }, - }, - { - label: "D32s_v3", - description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", - sku: { - name: "Standard_D32s_v3", - tier: "GeneralPurpose", - capacity: 32, - size: "64", - }, - }, - { - label: "D48s_v3", - description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", - sku: { - name: "Standard_D48s_v3", - tier: "GeneralPurpose", - capacity: 48, - size: "256", - }, - }, - { - label: "D64s_v3", - description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", - sku: { - name: "Standard_D64s_v3", - tier: "GeneralPurpose", - capacity: 64, - size: "256", - }, - }, + { + label: "B1ms", + description: "Basic, 1 vCore, 2GiB Memory, 32GB storage", + sku: { + name: "Standard_B1ms", + tier: "Burstable", + capacity: 1, + size: "32", + }, + group: recommendedGroup, + }, + { + label: "B2s", + description: "Basic, 2 vCore, 4GiB Memory, 32GB storage", + sku: { + name: "Standard_B2s", + tier: "Burstable", + capacity: 2, + size: "32", + }, + }, + { + label: "D2s_v3", + description: "General Purpose, 2 vCore, 8GiB Memory, 32GB storage", + sku: { + name: "Standard_D2s_v3", + tier: "GeneralPurpose", + capacity: 2, + size: "32", + }, + group: recommendedGroup, + }, + { + label: "D4s_v3", + description: "General Purpose, 4 vCore, 16GiB Memory, 32GB storage", + sku: { + name: "Standard_D4s_v3", + tier: "GeneralPurpose", + capacity: 4, + size: "32", + }, + }, + { + label: "D8s_v3", + description: "General Purpose, 8 vCore, 32GiB Memory, 64GB storage", + sku: { + name: "Standard_D8s_v3", + tier: "GeneralPurpose", + capacity: 8, + size: "64", + }, + }, + { + label: "D16s_v3", + description: "General Purpose, 16 vCore, 64GiB Memory, 64GB storage", + sku: { + name: "Standard_D16s_v3", + tier: "GeneralPurpose", + capacity: 16, + size: "64", + }, + }, + { + label: "D32s_v3", + description: "General Purpose, 32 vCore, 128GiB Memory, 64GB storage", + sku: { + name: "Standard_D32s_v3", + tier: "GeneralPurpose", + capacity: 32, + size: "64", + }, + }, + { + label: "D48s_v3", + description: "General Purpose, 48 vCore, 192GiB Memory, 256GB storage", + sku: { + name: "Standard_D48s_v3", + tier: "GeneralPurpose", + capacity: 48, + size: "256", + }, + }, + { + label: "D64s_v3", + description: "General Purpose, 64 vCore, 256GiB Memory, 256GB storage", + sku: { + name: "Standard_D64s_v3", + tier: "GeneralPurpose", + capacity: 64, + size: "256", + }, + }, ]; From 02dcc3153d8dc0641d04bc57016174654aa16b80 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Mon, 27 Nov 2023 02:08:26 +0200 Subject: [PATCH 28/33] squash! --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 48ee67fc3..bb94c33c7 100644 --- a/package.json +++ b/package.json @@ -1048,11 +1048,11 @@ "@types/gulp": "4.0.17", "@types/mocha": "10.0.6", "@types/mongodb": "4.0.6", - "@types/node": "20.9.4", + "@types/node": "20.10.0", "@types/pg": "8.10.9", "@types/vscode": "1.84.2", "@typescript-eslint/eslint-plugin": "6.12.0", - "@vscode/test-electron": "2.3.6", + "@vscode/test-electron": "2.3.8", "antlr4ts-cli": "0.5.0-alpha.4", "copy-webpack-plugin": "11.0.0", "eslint": "8.54.0", From b7ffef7bc4cd6567d8cd18e3774fec9743524645 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Mon, 27 Nov 2023 06:01:18 +0200 Subject: [PATCH 29/33] squash! --- CODE_OF_CONDUCT.md | 10 +- NOTICE.html | 5497 ++++++++++++++++++++++++++----------------- README.md | 145 +- SECURITY.md | 54 +- extension.bundle.ts | 84 +- gulpfile.ts | 39 +- main.js | 14 +- package.json | 2220 ++++++++--------- tsconfig.json | 52 +- webpack.config.js | 76 +- 10 files changed, 4756 insertions(+), 3435 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f9ba8cf65..bb1fb9ac7 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,9 +1,11 @@ # Microsoft Open Source Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). Resources: -- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) -- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) -- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with + questions or concerns diff --git a/NOTICE.html b/NOTICE.html index 3c64feaf0..78b671fd0 100644 --- a/NOTICE.html +++ b/NOTICE.html @@ -1,44 +1,52 @@ - + - - NOTICES AND INFORMATION - - - -

NOTICES AND INFORMATION

-

Do Not Translate or Localize

-

- This software incorporates material from third parties. - Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, - or you may send a check or money order for US $5.00, including the product name, - the open source component name, platform, and version number, to: -

-
- Source Code Compliance Team
- Microsoft Corporation
- One Microsoft Way
- Redmond, WA 98052
- USA -
-

- Notwithstanding any other terms, you may reverse engineer this software to the extent - required to debug changes to any libraries licensed under the GNU Lesser General Public License. -

-
    -
  1. -
    - - tslib 1.14.1 - 0BSD - -

    https://www.typescriptlang.org/

    -
    • Copyright (c) Microsoft Corporation
    -
    +	
    +		NOTICES AND INFORMATION
    +		
    +	
    +	
    +		

    NOTICES AND INFORMATION

    +

    Do Not Translate or Localize

    +

    + This software incorporates material from third parties. Microsoft + makes certain open source code available at + https://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including + the product name, the open source component name, platform, and + version number, to: +

    +
    + Source Code Compliance Team
    + Microsoft Corporation
    + One Microsoft Way
    + Redmond, WA 98052
    + USA +
    +

    + Notwithstanding any other terms, you may reverse engineer this + software to the extent required to debug changes to any libraries + licensed under the GNU Lesser General Public License. +

    +
      +
    1. +
      + tslib 1.14.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -51,17 +59,22 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    2. -
    3. -
      - - tslib 2.1.0 - 0BSD - -

      https://www.typescriptlang.org/

      -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    4. +
    5. +
      + tslib 2.1.0 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -74,17 +87,22 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    6. -
    7. -
      - - tslib 2.3.1 - 0BSD - -

      https://www.typescriptlang.org/

      -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    8. +
    9. +
      + tslib 2.3.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -97,17 +115,22 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    10. -
    11. -
      - - tslib 2.4.0 - 0BSD - -

      https://www.typescriptlang.org/

      -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    12. +
    13. +
      + tslib 2.4.0 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -120,17 +143,22 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    14. -
    15. -
      - - tslib 2.6.1 - 0BSD - -

      https://www.typescriptlang.org/

      -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    16. +
    17. +
      + tslib 2.6.1 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -143,17 +171,22 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    18. -
    19. -
      - - tslib 2.6.2 - 0BSD - -

      https://www.typescriptlang.org/

      -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    20. +
    21. +
      + tslib 2.6.2 - 0BSD +

      + https://www.typescriptlang.org/ +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -166,21 +199,28 @@ 

      NOTICES AND INFORMATION

      LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    22. -
    23. -
      - - bson 1.1.4 - Apache-2.0 - -

      https://github.com/mongodb/js-bson#readme

      -
      • Copyright 2009 Google Inc.
      • -
      • Copyright (c) 2014, Facebook, Inc.
      • -
      • copyright (c) 2019 Denis Pushkarev
      • -
      • Copyright (c) 2008, Fair Oaks Labs, Inc.
      • -
      • Copyright Joyent, Inc. and other Node contributors.
      -
      +        
      +
      +
    24. +
    25. +
      + bson 1.1.4 - Apache-2.0 +

      + https://github.com/mongodb/js-bson#readme +

      +
        +
      • Copyright 2009 Google Inc.
      • +
      • Copyright (c) 2014, Facebook, Inc.
      • +
      • copyright (c) 2019 Denis Pushkarev
      • +
      • Copyright (c) 2008, Fair Oaks Labs, Inc.
      • +
      • + Copyright Joyent, Inc. and other Node contributors. +
      • +
      +
                                                Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -383,17 +423,22 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    26. -
    27. -
      - - denque 1.4.1 - Apache-2.0 - -

      https://github.com/invertase/denque#readme

      -
      • Copyright (c) 2018 Mike Diarmid
      -
      +        
      +
      +
    28. +
    29. +
      + denque 1.4.1 - Apache-2.0 +

      + https://github.com/invertase/denque#readme +

      +
        +
      • Copyright (c) 2018 Mike Diarmid
      • +
      +
               Copyright (c) 2018 Mike Diarmid (Salakar) <mike.diarmid@gmail.com>
       
       Licensed under the Apache License, Version 2.0 (the "License");
      @@ -408,17 +453,21 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    30. -
    31. -
      - - jsbi 3.2.5 - Apache-2.0 - -

      https://github.com/GoogleChromeLabs/jsbi#readme

      - -
      +        
      +
      +
    32. +
    33. +
      + jsbi 3.2.5 - Apache-2.0 +

      + https://github.com/GoogleChromeLabs/jsbi#readme +

      + +
                                                Apache License
                                  Version 2.0, January 2004
                               https://www.apache.org/licenses/
      @@ -596,18 +645,23 @@ 

      NOTICES AND INFORMATION

      END OF TERMS AND CONDITIONS -
      -
      -
    34. -
    35. -
      - - mongodb 3.6.10 - Apache-2.0 - -

      https://github.com/mongodb/node-mongodb-native

      -
      • (c) 2012-present MongoDB
      • -
      • (c) 2009-2012 Christian Amor Kvalheim
      -
      +        
      +
      +
    36. +
    37. +
      + mongodb 3.6.10 - Apache-2.0 +

      + https://github.com/mongodb/node-mongodb-native +

      +
        +
      • (c) 2012-present MongoDB
      • +
      • (c) 2009-2012 Christian Amor Kvalheim
      • +
      +
               Apache License
                                  Version 2.0, January 2004
                               http://www.apache.org/licenses/
      @@ -809,17 +863,22 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    38. -
    39. -
      - - mongodb-extended-json 1.11.0 - Apache-2.0 - -

      http://github.com/mongodb-js/extended-json

      -
      • Copyright 2015 MongoDB Inc.
      -
      +        
      +
      +
    40. +
    41. +
      + mongodb-extended-json 1.11.0 - Apache-2.0 +

      + http://github.com/mongodb-js/extended-json +

      +
        +
      • Copyright 2015 MongoDB Inc.
      • +
      +
               Apache License
       Version 2.0, January 2004
       http://www.apache.org/licenses/
      @@ -1022,17 +1081,23 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    42. -
    43. -
      - - optional-require 1.1.8 - Apache-2.0 - -

      https://github.com/jchip/optional-require#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +        
      +
      +
    44. +
    45. +
      + optional-require 1.1.8 - Apache-2.0 +

      + https://github.com/jchip/optional-require#readme +

      +
        +
      • (c) Joel Chen (https://github.com/jchip)
      • +
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1130,17 +1195,22 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    46. -
    47. -
      - - require-at 1.0.6 - Apache-2.0 - -

      https://github.com/jchip/require-at#readme

      -
      • (c) Joel Chen (https://github.com/jchip)
      -
      +        
      +
      +
    48. +
    49. +
      + require-at 1.0.6 - Apache-2.0 +

      + https://github.com/jchip/require-at#readme +

      +
        +
      • (c) Joel Chen (https://github.com/jchip)
      • +
      +
               Apache License
       
       Version 2.0, January 2004
      @@ -1238,17 +1308,22 @@ 

      NOTICES AND INFORMATION

      See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    50. -
    51. -
      - - domelementtype 2.3.0 - BSD-2-Clause - -

      https://github.com/fb55/domelementtype#readme

      -
      • Copyright (c) Felix Bohm
      -
      +        
      +
      +
    52. +
    53. +
      + domelementtype 2.3.0 - BSD-2-Clause +

      + https://github.com/fb55/domelementtype#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1261,17 +1336,22 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    54. -
    55. -
      - - domhandler 4.3.1 - BSD-2-Clause - -

      https://github.com/fb55/domhandler#readme

      -
      • Copyright (c) Felix Bohm
      -
      +        
      +
      +
    56. +
    57. +
      + domhandler 4.3.1 - BSD-2-Clause +

      + https://github.com/fb55/domhandler#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1284,17 +1364,22 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    58. -
    59. -
      - - domutils 2.8.0 - BSD-2-Clause - -

      https://github.com/fb55/domutils#readme

      -
      • Copyright (c) Felix Bohm
      -
      +        
      +
      +
    60. +
    61. +
      + domutils 2.8.0 - BSD-2-Clause +

      + https://github.com/fb55/domutils#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1307,17 +1392,22 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    62. -
    63. -
      - - dotenv 8.6.0 - BSD-2-Clause - -

      https://github.com/motdotla/dotenv#readme

      -
      • Copyright (c) 2015, Scott Motte
      -
      +        
      +
      +
    64. +
    65. +
      + dotenv 8.6.0 - BSD-2-Clause +

      + https://github.com/motdotla/dotenv#readme +

      +
        +
      • Copyright (c) 2015, Scott Motte
      • +
      +
               Copyright (c) 2015, Scott Motte
       All rights reserved.
       
      @@ -1342,17 +1432,22 @@ 

      NOTICES AND INFORMATION

      OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    66. -
    67. -
      - - entities 2.2.0 - BSD-2-Clause - -

      https://github.com/fb55/entities#readme

      -
      • Copyright (c) Felix Bohm
      -
      +        
      +
      +
    68. +
    69. +
      + entities 2.2.0 - BSD-2-Clause +

      + https://github.com/fb55/entities#readme +

      +
        +
      • Copyright (c) Felix Bohm
      • +
      +
               Copyright (c) Felix Böhm
       All rights reserved.
       
      @@ -1365,17 +1460,23 @@ 

      NOTICES AND INFORMATION

      THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    70. -
    71. -
      - - webidl-conversions 3.0.1 - BSD-2-Clause - -

      https://github.com/jsdom/webidl-conversions#readme

      -
      • Copyright (c) 2014, Domenic Denicola
      -
      +        
      +
      +
    72. +
    73. +
      + webidl-conversions 3.0.1 - BSD-2-Clause +

      + https://github.com/jsdom/webidl-conversions#readme +

      +
        +
      • Copyright (c) 2014, Domenic Denicola
      • +
      +
               # The BSD 2-Clause License
       
       Copyright (c) 2014, Domenic Denicola
      @@ -1389,18 +1490,24 @@ 

      NOTICES AND INFORMATION

      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    74. -
    75. -
      - - antlr4ts 0.4.1-alpha.0 - BSD-3-Clause - -

      https://github.com/tunnelvisionlabs/antlr4ts#readme

      -
      • Copyright 2016 The ANTLR Project.
      • -
      • Copyright (c) 2016 The ANTLR Project
      -
      +        
      +
      +
    76. +
    77. +
      + antlr4ts 0.4.1-alpha.0 - BSD-3-Clause +

      + https://github.com/tunnelvisionlabs/antlr4ts#readme +

      +
        +
      • Copyright 2016 The ANTLR Project.
      • +
      • Copyright (c) 2016 The ANTLR Project
      • +
      +
               [The "BSD license"]
       Copyright (c) 2016 The ANTLR Project
       All rights reserved.
      @@ -1429,17 +1536,22 @@ 

      NOTICES AND INFORMATION

      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    78. -
    79. -
      - - moo 0.5.1 - BSD-3-Clause - -

      https://github.com/tjvr/moo#readme

      -
      • Copyright (c) 2017, Tim Radvan
      -
      +        
      +
      +
    80. +
    81. +
      + moo 0.5.1 - BSD-3-Clause +

      + https://github.com/tjvr/moo#readme +

      +
        +
      • Copyright (c) 2017, Tim Radvan
      • +
      +
               BSD 3-Clause License
       
       Copyright (c) 2017, Tim Radvan (tjvr)
      @@ -1470,17 +1582,20 @@ 

      NOTICES AND INFORMATION

      OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
      -
      -
    82. -
    83. -
      - - railroad-diagrams 1.0.0 - CC0-1.0 - -

      https://github.com/tabatkins/railroad-diagrams

      - -
      +        
      +
      +
    84. +
    85. +
      + railroad-diagrams 1.0.0 - CC0-1.0 +

      + https://github.com/tabatkins/railroad-diagrams +

      + +
               Creative Commons Legal Code
       
       CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
      @@ -1522,17 +1637,26 @@ 

      NOTICES AND INFORMATION

      c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. -
      -
      -
    86. -
    87. -
      - - graceful-fs 4.2.10 - ISC - -

      https://github.com/isaacs/node-graceful-fs#readme

      -
      • Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      -
      +        
      +
      +
    88. +
    89. +
      + graceful-fs 4.2.10 - ISC +

      + https://github.com/isaacs/node-graceful-fs#readme +

      +
        +
      • + Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben + Noordhuis, and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
      @@ -1549,17 +1673,22 @@ 

      NOTICES AND INFORMATION

      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    90. -
    91. -
      - - inherits 2.0.4 - ISC - -

      https://github.com/isaacs/inherits#readme

      -
      • Copyright (c) Isaac Z. Schlueter
      -
      +        
      +
      +
    92. +
    93. +
      + inherits 2.0.4 - ISC +

      + https://github.com/isaacs/inherits#readme +

      +
        +
      • Copyright (c) Isaac Z. Schlueter
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter
      @@ -1577,17 +1706,25 @@ 

      NOTICES AND INFORMATION

      PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    94. -
    95. -
      - - lru-cache 6.0.0 - ISC - -

      https://github.com/isaacs/node-lru-cache#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +        
      +
      +
    96. +
    97. +
      + lru-cache 6.0.0 - ISC +

      + https://github.com/isaacs/node-lru-cache#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1604,17 +1741,22 @@ 

      NOTICES AND INFORMATION

      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    98. -
    99. -
      - - pg-int8 1.0.1 - ISC - -

      https://github.com/charmander/pg-int8#readme

      -
      • Copyright (c) 2017, Charmander
      -
      +        
      +
      +
    100. +
    101. +
      + pg-int8 1.0.1 - ISC +

      + https://github.com/charmander/pg-int8#readme +

      +
        +
      • Copyright (c) 2017, Charmander
      • +
      +
               Copyright © 2017, Charmander <~@charmander.me>
       
       Permission to use, copy, modify, and/or distribute this software for any
      @@ -1629,18 +1771,28 @@ 

      NOTICES AND INFORMATION

      OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    102. -
    103. -
      - - sax 1.2.4 - ISC - -

      https://github.com/isaacs/sax-js#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      • -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +        
      +
      +
    104. +
    105. +
      + sax 1.2.4 - ISC +

      + https://github.com/isaacs/sax-js#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      • + Copyright Mathias Bynens + <https://mathiasbynens.be/> +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1683,19 +1835,26 @@ 

      NOTICES AND INFORMATION

      OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    106. -
    107. -
      - - semver 6.3.0 - ISC - -

      https://github.com/npm/node-semver#readme

      -
      • Copyright Isaac Z.
      • -
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +        
      +
      +
    108. +
    109. +
      + semver 6.3.0 - ISC +

      + https://github.com/npm/node-semver#readme +

      +
        +
      • Copyright Isaac Z.
      • +
      • Copyright Isaac Z. Schlueter
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1712,18 +1871,25 @@ 

      NOTICES AND INFORMATION

      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    110. -
    111. -
      - - semver 7.5.2 - ISC - -

      https://github.com/npm/node-semver#readme

      -
      • Copyright Isaac Z. Schlueter
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +        
      +
      +
    112. +
    113. +
      + semver 7.5.2 - ISC +

      + https://github.com/npm/node-semver#readme +

      +
        +
      • Copyright Isaac Z. Schlueter
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1740,17 +1906,26 @@ 

      NOTICES AND INFORMATION

      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    114. -
    115. -
      - - universal-user-agent 6.0.0 - ISC - -

      https://github.com/gr2m/universal-user-agent#readme

      -
      • Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      -
      +        
      +
      +
    116. +
    117. +
      + universal-user-agent 6.0.0 - ISC +

      + https://github.com/gr2m/universal-user-agent#readme +

      +
        +
      • + Copyright (c) 2018, Gregor Martynus + (https://github.com/gr2m) +
      • +
      +
               # [ISC License](https://spdx.org/licenses/ISC)
       
       Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
      @@ -1759,17 +1934,24 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    118. -
    119. -
      - - yallist 4.0.0 - ISC - -

      https://github.com/isaacs/yallist#readme

      -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +        
      +
      +
    120. +
    121. +
      + yallist 4.0.0 - ISC +

      + https://github.com/isaacs/yallist#readme +

      +
        +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               The ISC License
       
       Copyright (c) Isaac Z. Schlueter and Contributors
      @@ -1786,17 +1968,23 @@ 

      NOTICES AND INFORMATION

      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -
      -
      -
    122. -
    123. -
      - - @azure/abort-controller 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    124. +
    125. +
      + @azure/abort-controller 1.0.2 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1819,17 +2007,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    126. -
    127. -
      - - @azure/arm-cosmosdb 15.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    128. +
    129. +
      + @azure/arm-cosmosdb 15.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/arm-cosmosdb +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1851,17 +2045,23 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    130. -
    131. -
      - - @azure/arm-postgresql 6.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    132. +
    133. +
      + @azure/arm-postgresql 6.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -1883,17 +2083,25 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    134. -
    135. -
      - - @azure/arm-postgresql-flexible 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    136. +
    137. +
      + + @azure/arm-postgresql-flexible 5.0.0 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/postgresql/arm-postgresql-flexible +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -1938,17 +2146,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    138. -
    139. -
      - - @azure/arm-resources 4.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    140. +
    141. +
      + @azure/arm-resources 4.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/resources/arm-resources +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -1971,17 +2185,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    142. -
    143. -
      - - @azure/arm-resources 5.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    144. +
    145. +
      + @azure/arm-resources 5.0.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Microsoft
      @@ -2003,17 +2223,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    146. -
    147. -
      - - @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid

      - -
      +        
      +
      +
    148. +
    149. +
      + + @azure/arm-resources-profile-2020-09-01-hybrid 2.0.0 - + MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources/arm-resources-profile-2020-09-01-hybrid +

      + +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2058,18 +2285,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    150. -
    151. -
      - - @azure/arm-resources-subscriptions 2.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions

      -
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    152. +
    153. +
      + + @azure/arm-resources-subscriptions 2.0.1 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/resources-subscriptions/arm-resources-subscriptions +

      +
        +
      • Copyright (c) 2022 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2091,18 +2326,24 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    154. -
    155. -
      - - @azure/arm-storage 18.2.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage

      -
      • Copyright (c) 2023 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    156. +
    157. +
      + @azure/arm-storage 18.2.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage +

      +
        +
      • Copyright (c) 2023 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2023 Microsoft
      @@ -2124,19 +2365,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    158. -
    159. -
      - - @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) 2022 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    160. +
    161. +
      + + @azure/arm-storage-profile-2020-09-01-hybrid 2.0.0 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/arm-storage-profile-2020-09-01-hybrid +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) 2022 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2022 Microsoft
      @@ -2181,18 +2430,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    162. -
    163. -
      - - @azure/core-asynciterator-polyfill 1.0.2 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    164. +
    165. +
      + + @azure/core-asynciterator-polyfill 1.0.2 - MIT + +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-asynciterator-polyfill/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2215,18 +2472,24 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    166. -
    167. -
      - - @azure/core-auth 1.5.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    168. +
    169. +
      + @azure/core-auth 1.5.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2249,19 +2512,28 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    170. -
    171. -
      - - @azure/core-client 1.7.3 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const CollectionFormatToDelimiterMap CSV
      -
      +        
      +
      +
    172. +
    173. +
      + @azure/core-client 1.7.3 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) Microsoft Corporation. const + CollectionFormatToDelimiterMap CSV +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2284,18 +2556,24 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    174. -
    175. -
      - - @azure/core-lro 2.5.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    176. +
    177. +
      + @azure/core-lro 2.5.4 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2318,17 +2596,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    178. -
    179. -
      - - @azure/core-paging 1.2.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    180. +
    181. +
      + @azure/core-paging 1.2.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2351,19 +2635,28 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    182. -
    183. -
      - - @azure/core-rest-pipeline 1.12.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft Corporation. const RedactedString REDACTED Make
      -
      +        
      +
      +
    184. +
    185. +
      + @azure/core-rest-pipeline 1.12.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) Microsoft Corporation. const + RedactedString REDACTED Make +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2386,18 +2679,24 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    186. -
    187. -
      - - @azure/core-tracing 1.0.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    188. +
    189. +
      + @azure/core-tracing 1.0.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2420,18 +2719,24 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    190. -
    191. -
      - - @azure/core-util 1.4.0 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    192. +
    193. +
      + @azure/core-util 1.4.0 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/ +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2454,18 +2759,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    194. -
    195. -
      - - @azure/cosmos 3.15.1 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) 2012-2015 Karan Lyons https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js
      -
      +        
      +
      +
    196. +
    197. +
      + @azure/cosmos 3.15.1 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/cosmosdb/cosmos/README.md +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • + Copyright (c) 2012-2015 Karan Lyons + https://github.com/karanlyons/murmurHash3.js/blob/c1778f75792abef7bdd74bc85d2d4e1a3d25cfe9/murmurHash3.js +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2488,18 +2802,24 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    198. -
    199. -
      - - @azure/logger 1.0.4 - MIT - -

      https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md

      -
      • Copyright (c) 2020 Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    200. +
    201. +
      + @azure/logger 1.0.4 - MIT +

      + https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md +

      +
        +
      • Copyright (c) 2020 Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2020 Microsoft
      @@ -2522,18 +2842,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    202. -
    203. -
      - - @azure/ms-rest-azure-js 2.1.0 - MIT - -

      https://github.com/Azure/ms-rest-azure-js

      -
      • Copyright (c) 2017
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    204. +
    205. +
      + @azure/ms-rest-azure-js 2.1.0 - MIT +

      + https://github.com/Azure/ms-rest-azure-js +

      +
        +
      • Copyright (c) 2017
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               MIT License
       
       Copyright (c) 2017 MIT
      @@ -2556,19 +2881,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    206. -
    207. -
      - - @azure/ms-rest-js 2.7.0 - MIT - -

      https://github.com/Azure/ms-rest-js

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      -
      +        
      +
      +
    208. +
    209. +
      + @azure/ms-rest-js 2.7.0 - MIT +

      + https://github.com/Azure/ms-rest-js +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright (c) 2010-2016 Robert Kieffer and other + contributors +
      • +
      +
                   MIT License
       
           Copyright (c) Microsoft Corporation. All rights reserved.
      @@ -2591,22 +2924,31 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE -
      -
      -
    210. -
    211. -
      - - @microsoft/1ds-core-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • copyright Microsoft 2018
      • -
      • copyright Microsoft 2019
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • copyright Microsoft 2019 Simplified
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018 import AppInsightsCore as InternalCore
      -
      +        
      +
      +
    212. +
    213. +
      + @microsoft/1ds-core-js 3.2.3 - MIT +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • copyright Microsoft 2018
      • +
      • copyright Microsoft 2019
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • copyright Microsoft 2019 Simplified
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • + copyright Microsoft 2018 import AppInsightsCore as + InternalCore +
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       MIT License
      @@ -2628,24 +2970,39 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    214. -
    215. -
      - - @microsoft/1ds-post-js 3.2.3 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • copyright Microsoft 2018
      • -
      • copyright Microsoft 2020
      • -
      • copyright Microsoft 2018-2020
      • -
      • copyright Microsoft 2022 Simple
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • copyright Microsoft 2018-2020 import IExtendedAppInsightsCore, SendRequestReason, EventSendType
      • -
      • copyright Microsoft 2018-2020 import IPerfManagerProvider, IValueSanitizer, FieldValueSanitizerType, FieldValueSanitizerFunc, SendRequestReason, EventSendType
      -
      +        
      +
      +
    216. +
    217. +
      + @microsoft/1ds-post-js 3.2.3 - MIT +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • copyright Microsoft 2018
      • +
      • copyright Microsoft 2020
      • +
      • copyright Microsoft 2018-2020
      • +
      • copyright Microsoft 2022 Simple
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • + copyright Microsoft 2018-2020 import + IExtendedAppInsightsCore, SendRequestReason, + EventSendType +
      • +
      • + copyright Microsoft 2018-2020 import + IPerfManagerProvider, IValueSanitizer, + FieldValueSanitizerType, FieldValueSanitizerFunc, + SendRequestReason, EventSendType +
      • +
      +
               Copyright (c) Microsoft Corporation.
       
       MIT License
      @@ -2667,18 +3024,26 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    218. -
    219. -
      - - @microsoft/applicationinsights-core-js 2.8.4 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      +        
      +
      +
    220. +
    221. +
      + + @microsoft/applicationinsights-core-js 2.8.4 - MIT + +

      + https://github.com/microsoft/ApplicationInsights-JS#readme +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      +
                   MIT License
       
           Copyright (c) Microsoft Corporation. All rights reserved.
      @@ -2701,18 +3066,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE -
      -
      -
    222. -
    223. -
      - - @microsoft/applicationinsights-shims 2.0.1 - MIT - -

      https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Microsoft and contributors.
      -
      +        
      +
      +
    224. +
    225. +
      + + @microsoft/applicationinsights-shims 2.0.1 - MIT + +

      + https://github.com/microsoft/ApplicationInsights-JS/tree/master/tools/shims +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • Copyright (c) Microsoft and contributors.
      • +
      +
                   MIT License
       
           Copyright (c) Microsoft Corporation. All rights reserved.
      @@ -2735,33 +3108,57 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE -
      -
      -
    226. -
    227. -
      - - @microsoft/dynamicproto-js 1.1.6 - MIT - -

      https://github.com/microsoft/DynamicProto-JS#readme

      -
      • (c) James Halliday
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) 2012 Maximilian Antoni
      • -
      • Copyright (c) 2013 Maximilian Antoni
      • -
      • Copyright (c) 2020 Oliver Nightingale
      • -
      • Copyright (c) 2020 Oliver Nightingale A
      • -
      • Copyright (c) 2020 Oliver Nightingale An
      • -
      • Copyright (c) Microsoft and contributors
      • -
      • Copyright (c) 2010-2013 Christian Johansen
      • -
      • Copyright (c) 2010-2014 Christian Johansen
      • -
      • Copyright (c) 2011 Sven Fuchs, Christian Johansen
      • -
      • Copyright Joyent, Inc. and other Node contributors
      • -
      • Copyright jQuery Foundation and other contributors
      • -
      • Copyright 2013 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
      • -
      • Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
      • -
      • Copyright 2006 Google Inc. https://code.google.com/p/google-diff-match-patch
      -
      +        
      +
      +
    228. +
    229. +
      + @microsoft/dynamicproto-js 1.1.6 - MIT +

      + https://github.com/microsoft/DynamicProto-JS#readme +

      +
        +
      • (c) James Halliday
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) 2012 Maximilian Antoni
      • +
      • Copyright (c) 2013 Maximilian Antoni
      • +
      • Copyright (c) 2020 Oliver Nightingale
      • +
      • Copyright (c) 2020 Oliver Nightingale A
      • +
      • Copyright (c) 2020 Oliver Nightingale An
      • +
      • Copyright (c) Microsoft and contributors
      • +
      • Copyright (c) 2010-2013 Christian Johansen
      • +
      • Copyright (c) 2010-2014 Christian Johansen
      • +
      • + Copyright (c) 2011 Sven Fuchs, Christian Johansen +
      • +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      • + Copyright jQuery Foundation and other contributors +
      • +
      • + Copyright 2013 jQuery Foundation, Inc. and other + contributors +
      • +
      • + Copyright (c) 2010-2014, Christian Johansen, + christian@cjohansen.no +
      • +
      • + Copyright 2005, 2014 jQuery Foundation, Inc. and + other contributors +
      • +
      • + Copyright 2006 Google Inc. + https://code.google.com/p/google-diff-match-patch +
      • +
      +
                   MIT License
       
           Copyright (c) Microsoft Corporation.
      @@ -2784,17 +3181,20 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE -
      -
      -
    230. -
    231. -
      - - @selderee/plugin-htmlparser2 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      +        
      +
      +
    232. +
    233. +
      + @selderee/plugin-htmlparser2 0.6.0 - MIT +

      + https://github.com/mxxii/selderee +

      + +
               MIT License
       
       Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      @@ -2817,17 +3217,20 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    234. -
    235. -
      - - @tootallnate/once 1.1.2 - MIT - -

      https://github.com/TooTallNate/once#readme

      - -
      +        
      +
      +
    236. +
    237. +
      + @tootallnate/once 1.1.2 - MIT +

      + https://github.com/TooTallNate/once#readme +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2837,17 +3240,22 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    238. -
    239. -
      - - @tootallnate/once 2.0.0 - MIT - -

      https://github.com/TooTallNate/once#readme

      -
      • Copyright (c) 2020 Nathan Rajlich
      -
      +        
      +
      +
    240. +
    241. +
      + @tootallnate/once 2.0.0 - MIT +

      + https://github.com/TooTallNate/once#readme +

      +
        +
      • Copyright (c) 2020 Nathan Rajlich
      • +
      +
               MIT License
       
       Copyright (c) 2020 Nathan Rajlich
      @@ -2870,17 +3278,17 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    242. -
    243. -
      - - @typescript-plus/fast-memoize-decorator 0.1.0 - MIT - - - -
      +        
      +
      +
    244. +
    245. +
      + + @typescript-plus/fast-memoize-decorator 0.1.0 - MIT + + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -2890,18 +3298,24 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    246. -
    247. -
      - - @vscode/extension-telemetry 0.6.2 - MIT - -

      https://github.com/Microsoft/vscode-extension-telemetry#readme

      -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright (c) Microsoft and contributors
      -
      +        
      +
      +
    248. +
    249. +
      + @vscode/extension-telemetry 0.6.2 - MIT +

      + https://github.com/Microsoft/vscode-extension-telemetry#readme +

      +
        +
      • Copyright (c) Microsoft Corporation
      • +
      • Copyright (c) Microsoft and contributors
      • +
      +
               vscode-extension-telemetry
       
       The MIT License (MIT)
      @@ -2925,17 +3339,18 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    250. -
    251. -
      - - 1to2 1.0.0 - MIT - - -
      • Copyright (c) 2014 3VOT
      -
      +        
      +
      +
    252. +
    253. +
      + 1to2 1.0.0 - MIT + +
        +
      • Copyright (c) 2014 3VOT
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 3VOT
      @@ -2957,18 +3372,24 @@ 

      NOTICES AND INFORMATION

      IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    254. -
    255. -
      - - abort-controller 3.0.0 - MIT - -

      https://github.com/mysticatea/abort-controller#readme

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2017 Toru Nagashima
      -
      +        
      +
      +
    256. +
    257. +
      + abort-controller 3.0.0 - MIT +

      + https://github.com/mysticatea/abort-controller#readme +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) 2017 Toru Nagashima
      • +
      +
               MIT License
       
       Copyright (c) 2017 Toru Nagashima
      @@ -2991,17 +3412,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    258. -
    259. -
      - - agent-base 6.0.2 - MIT - -

      https://github.com/TooTallNate/node-agent-base#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +        
      +
      +
    260. +
    261. +
      + agent-base 6.0.2 - MIT +

      + https://github.com/TooTallNate/node-agent-base#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3011,17 +3441,22 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    262. -
    263. -
      - - async 3.2.3 - MIT - -

      https://caolan.github.io/async/

      -
      • Copyright (c) 2010-2018 Caolan McMahon
      -
      +        
      +
      +
    264. +
    265. +
      + async 3.2.3 - MIT +

      + https://caolan.github.io/async/ +

      +
        +
      • Copyright (c) 2010-2018 Caolan McMahon
      • +
      +
               Copyright (c) 2010-2018 Caolan McMahon
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3042,17 +3477,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    266. -
    267. -
      - - asynckit 0.4.0 - MIT - -

      https://github.com/alexindigo/asynckit#readme

      -
      • Copyright (c) 2016 Alex Indigo
      -
      +        
      +
      +
    268. +
    269. +
      + asynckit 0.4.0 - MIT +

      + https://github.com/alexindigo/asynckit#readme +

      +
        +
      • Copyright (c) 2016 Alex Indigo
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Alex Indigo
      @@ -3075,17 +3515,20 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    270. -
    271. -
      - - axios 0.21.4 - MIT - -

      https://axios-http.com/

      - -
      +        
      +
      +
    272. +
    273. +
      + axios 0.21.4 - MIT +

      + https://axios-http.com/ +

      + +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3106,17 +3549,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    274. -
    275. -
      - - axios 0.26.1 - MIT - -

      https://axios-http.com/

      -
      • Copyright (c) 2014-present Matt Zabriskie
      -
      +        
      +
      +
    276. +
    277. +
      + axios 0.26.1 - MIT +

      + https://axios-http.com/ +

      +
        +
      • Copyright (c) 2014-present Matt Zabriskie
      • +
      +
               Copyright (c) 2014-present Matt Zabriskie
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3137,17 +3585,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    278. -
    279. -
      - - bl 2.2.1 - MIT - -

      https://github.com/rvagg/bl

      -
      • Copyright (c) 2013-2018 bl contributors
      -
      +        
      +
      +
    280. +
    281. +
      + bl 2.2.1 - MIT +

      + https://github.com/rvagg/bl +

      +
        +
      • Copyright (c) 2013-2018 bl contributors
      • +
      +
               The MIT License (MIT)
       =====================
       
      @@ -3162,17 +3615,21 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    282. -
    283. -
      - - buffer-writer 2.0.0 - MIT - -

      https://github.com/brianc/node-buffer-writer#readme

      - -
      +        
      +
      +
    284. +
    285. +
      + buffer-writer 2.0.0 - MIT +

      + https://github.com/brianc/node-buffer-writer#readme +

      + +
               The MIT License (MIT)
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3193,17 +3650,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    286. -
    287. -
      - - combined-stream 1.0.8 - MIT - -

      https://github.com/felixge/node-combined-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +        
      +
      +
    288. +
    289. +
      + combined-stream 1.0.8 - MIT +

      + https://github.com/felixge/node-combined-stream +

      +
        +
      • + Copyright (c) 2011 Debuggable Limited + <felix@debuggable.com> +
      • +
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3224,17 +3690,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    290. -
    291. -
      - - commander 2.20.3 - MIT - -

      https://github.com/tj/commander.js#readme

      -
      • Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      -
      +        
      +
      +
    292. +
    293. +
      + commander 2.20.3 - MIT +

      + https://github.com/tj/commander.js#readme +

      +
        +
      • + Copyright (c) 2011 TJ Holowaychuk + <tj@vision-media.ca> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3258,17 +3732,24 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    294. -
    295. -
      - - core-util-is 1.0.2 - MIT - -

      https://github.com/isaacs/core-util-is#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +        
      +
      +
    296. +
    297. +
      + core-util-is 1.0.2 - MIT +

      + https://github.com/isaacs/core-util-is#readme +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Copyright Node.js contributors. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3289,17 +3770,18 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    298. -
    299. -
      - - dayjs 1.11.2 - MIT - -

      https://day.js.org/

      -
      • Copyright (c) 2018-present, iamkun
      -
      +        
      +
      +
    300. +
    301. +
      + dayjs 1.11.2 - MIT +

      https://day.js.org/

      +
        +
      • Copyright (c) 2018-present, iamkun
      • +
      +
               MIT License
       
       Copyright (c) 2018-present, iamkun
      @@ -3322,18 +3804,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    302. -
    303. -
      - - debug 4.3.4 - MIT - -

      https://github.com/debug-js/debug#readme

      -
      • Copyright (c) 2018-2021 Josh Junon
      • -
      • Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      -
      +        
      +
      +
    304. +
    305. +
      + debug 4.3.4 - MIT +

      + https://github.com/debug-js/debug#readme +

      +
        +
      • Copyright (c) 2018-2021 Josh Junon
      • +
      • + Copyright (c) 2014-2017 TJ Holowaychuk + <tj@vision-media.ca> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
      @@ -3355,17 +3845,25 @@ 

      NOTICES AND INFORMATION

      SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    306. -
    307. -
      - - deepmerge 4.2.2 - MIT - -

      https://github.com/TehShrike/deepmerge

      -
      • Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      -
      +        
      +
      +
    308. +
    309. +
      + deepmerge 4.2.2 - MIT +

      + https://github.com/TehShrike/deepmerge +

      +
        +
      • + Copyright (c) 2012 James Halliday, Josh Duff, and + other contributors +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 James Halliday, Josh Duff, and other contributors
      @@ -3388,18 +3886,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    310. -
    311. -
      - - define-lazy-prop 2.0.0 - MIT - -

      https://github.com/sindresorhus/define-lazy-prop#readme

      -
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +        
      +
      +
    312. +
    313. +
      + define-lazy-prop 2.0.0 - MIT +

      + https://github.com/sindresorhus/define-lazy-prop#readme +

      +
        +
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3410,17 +3917,25 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    314. -
    315. -
      - - delayed-stream 1.0.0 - MIT - -

      https://github.com/felixge/node-delayed-stream

      -
      • Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
      -
      +        
      +
      +
    316. +
    317. +
      + delayed-stream 1.0.0 - MIT +

      + https://github.com/felixge/node-delayed-stream +

      +
        +
      • + Copyright (c) 2011 Debuggable Limited + <felix@debuggable.com> +
      • +
      +
               Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3441,17 +3956,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    318. -
    319. -
      - - discontinuous-range 1.0.0 - MIT - -

      https://github.com/dtudury/discontinuous-range

      -
      • Copyright (c) 2014 David Tudury
      -
      +        
      +
      +
    320. +
    321. +
      + discontinuous-range 1.0.0 - MIT +

      + https://github.com/dtudury/discontinuous-range +

      +
        +
      • Copyright (c) 2014 David Tudury
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 David Tudury
      @@ -3474,17 +3994,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    322. -
    323. -
      - - dom-serializer 1.4.1 - MIT - -

      https://github.com/cheeriojs/dom-renderer#readme

      -
      • Copyright (c) 2014 The cheeriojs contributors
      -
      +        
      +
      +
    324. +
    325. +
      + dom-serializer 1.4.1 - MIT +

      + https://github.com/cheeriojs/dom-renderer#readme +

      +
        +
      • Copyright (c) 2014 The cheeriojs contributors
      • +
      +
               License
       
       (The MIT License)
      @@ -3497,17 +4023,22 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    326. -
    327. -
      - - duplexer 0.1.1 - MIT - -

      https://github.com/Raynos/duplexer

      -
      • Copyright (c) 2012 Raynos.
      -
      +        
      +
      +
    328. +
    329. +
      + duplexer 0.1.1 - MIT +

      + https://github.com/Raynos/duplexer +

      +
        +
      • Copyright (c) 2012 Raynos.
      • +
      +
               Copyright (c) 2012 Raynos.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3527,18 +4058,27 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    330. -
    331. -
      - - escape-string-regexp 2.0.0 - MIT - -

      https://github.com/sindresorhus/escape-string-regexp#readme

      -
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +        
      +
      +
    332. +
    333. +
      + escape-string-regexp 2.0.0 - MIT +

      + https://github.com/sindresorhus/escape-string-regexp#readme +

      +
        +
      • (c) Sindre Sorhus (https://sindresorhus.com)
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -3549,17 +4089,22 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    334. -
    335. -
      - - event-stream 4.0.1 - MIT - -

      http://github.com/dominictarr/event-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +        
      +
      +
    336. +
    337. +
      + event-stream 4.0.1 - MIT +

      + http://github.com/dominictarr/event-stream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3585,18 +4130,24 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    338. -
    339. -
      - - event-target-shim 5.0.1 - MIT - -

      https://github.com/mysticatea/event-target-shim

      -
      • copyright 2015 Toru Nagashima
      • -
      • Copyright (c) 2015 Toru Nagashima
      -
      +        
      +
      +
    340. +
    341. +
      + event-target-shim 5.0.1 - MIT +

      + https://github.com/mysticatea/event-target-shim +

      +
        +
      • copyright 2015 Toru Nagashima
      • +
      • Copyright (c) 2015 Toru Nagashima
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2015 Toru Nagashima
      @@ -3620,18 +4171,24 @@ 

      NOTICES AND INFORMATION

      SOFTWARE. -
      -
      -
    342. -
    343. -
      - - fast-json-stable-stringify 2.1.0 - MIT - -

      https://github.com/epoberezkin/fast-json-stable-stringify

      -
      • Copyright (c) 2013 James Halliday
      • -
      • Copyright (c) 2017 Evgeny Poberezkin
      -
      +        
      +
      +
    344. +
    345. +
      + fast-json-stable-stringify 2.1.0 - MIT +

      + https://github.com/epoberezkin/fast-json-stable-stringify +

      +
        +
      • Copyright (c) 2013 James Halliday
      • +
      • Copyright (c) 2017 Evgeny Poberezkin
      • +
      +
               This software is released under the MIT license:
       
       Copyright (c) 2017 Evgeny Poberezkin
      @@ -3654,17 +4211,23 @@ 

      NOTICES AND INFORMATION

      IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    346. -
    347. -
      - - fast-memoize 2.5.2 - MIT - -

      https://github.com/caiogondim/fast-memoize#readme

      -
      • Copyright (c) 2016 Caio Gondim
      -
      +        
      +
      +
    348. +
    349. +
      + fast-memoize 2.5.2 - MIT +

      + https://github.com/caiogondim/fast-memoize#readme +

      +
        +
      • Copyright (c) 2016 Caio Gondim
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Caio Gondim
      @@ -3687,17 +4250,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    350. -
    351. -
      - - follow-redirects 1.14.8 - MIT - -

      https://github.com/follow-redirects/follow-redirects

      -
      • Copyright 2014-present Olivier Lalonde <olalonde@gmail.com> , James Talmage <james@talmage.io> , Ruben Verborgh
      -
      +        
      +
      +
    352. +
    353. +
      + follow-redirects 1.14.8 - MIT +

      + https://github.com/follow-redirects/follow-redirects +

      +
        +
      • + Copyright 2014-present Olivier Lalonde + <olalonde@gmail.com> , James Talmage + <james@talmage.io> , Ruben Verborgh +
      • +
      +
               Copyright 2014–present Olivier Lalonde <olalonde@gmail.com>, James Talmage <james@talmage.io>, Ruben Verborgh
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of
      @@ -3717,17 +4290,25 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    354. -
    355. -
      - - form-data 2.5.1 - MIT - -

      https://github.com/form-data/form-data#readme

      -
      • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
      -
      +        
      +
      +
    356. +
    357. +
      + form-data 2.5.1 - MIT +

      + https://github.com/form-data/form-data#readme +

      +
        +
      • + Copyright (c) 2012 Felix Geisendorfer + (felix@debuggable.com) and contributors +
      • +
      +
               Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
       
        Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3748,17 +4329,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    358. -
    359. -
      - - form-data 4.0.0 - MIT - -

      https://github.com/form-data/form-data#readme

      -
      • Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors
      -
      +        
      +
      +
    360. +
    361. +
      + form-data 4.0.0 - MIT +

      + https://github.com/form-data/form-data#readme +

      +
        +
      • + Copyright (c) 2012 Felix Geisendorfer + (felix@debuggable.com) and contributors +
      • +
      +
               Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
       
        Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -3779,17 +4368,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    362. -
    363. -
      - - from 0.1.7 - MIT - -

      https://github.com/dominictarr/from#readme

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +        
      +
      +
    364. +
    365. +
      + from 0.1.7 - MIT +

      + https://github.com/dominictarr/from#readme +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -3815,19 +4409,30 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    366. -
    367. -
      - - fs-extra 8.1.0 - MIT - -

      https://github.com/jprichardson/node-fs-extra

      -
      • Copyright (c) 2011-2017 JP Richardson
      • -
      • Copyright (c) 2011-2017 JP Richardson (https://github.com/jprichardson)
      • -
      • Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
      -
      +        
      +
      +
    368. +
    369. +
      + fs-extra 8.1.0 - MIT +

      + https://github.com/jprichardson/node-fs-extra +

      +
        +
      • Copyright (c) 2011-2017 JP Richardson
      • +
      • + Copyright (c) 2011-2017 JP Richardson + (https://github.com/jprichardson) +
      • +
      • + Copyright (c) 2014-2016 Jonathan Ong + me@jongleberry.com and Contributors +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2011-2017 JP Richardson
      @@ -3844,17 +4449,21 @@ 

      NOTICES AND INFORMATION

      OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    370. -
    371. -
      - - he 1.2.0 - MIT - -

      https://mths.be/he

      -
      • Copyright Mathias Bynens <https://mathiasbynens.be/>
      -
      +        
      +
      +
    372. +
    373. +
      + he 1.2.0 - MIT +

      https://mths.be/he

      +
        +
      • + Copyright Mathias Bynens + <https://mathiasbynens.be/> +
      • +
      +
               Copyright Mathias Bynens <https://mathiasbynens.be/>
       
       Permission is hereby granted, free of charge, to any person obtaining
      @@ -3876,17 +4485,25 @@ 

      NOTICES AND INFORMATION

      OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    374. -
    375. -
      - - htmlparser2 6.1.0 - MIT - -

      https://github.com/fb55/htmlparser2#readme

      -
      • Copyright 2010, 2011, Chris Winberry <chris@winberry.net>
      -
      +        
      +
      +
    376. +
    377. +
      + htmlparser2 6.1.0 - MIT +

      + https://github.com/fb55/htmlparser2#readme +

      +
        +
      • + Copyright 2010, 2011, Chris Winberry + <chris@winberry.net> +
      • +
      +
               Copyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.
       Permission is hereby granted, free of charge, to any person obtaining a copy
       of this software and associated documentation files (the "Software"), to
      @@ -3905,18 +4522,30 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    378. -
    379. -
      - - html-to-text 8.2.0 - MIT - -

      https://github.com/html-to-text/node-html-to-text

      -
      • Portions Copyright (c) 2020 KillyMXI <killy@mxii.eu.org>
      • -
      • Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
      -
      +        
      +
      +
    380. +
    381. +
      + html-to-text 8.2.0 - MIT +

      + https://github.com/html-to-text/node-html-to-text +

      +
        +
      • + Portions Copyright (c) 2020 KillyMXI + <killy@mxii.eu.org> +
      • +
      • + Portions Copyright (c) 2012-2019 werk85 + <malte@werk85.de> +
      • +
      +
               MIT License
       
       Portions Copyright (c) 2012-2019 werk85 <malte@werk85.de>
      @@ -3943,17 +4572,26 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    382. -
    383. -
      - - http-proxy-agent 4.0.1 - MIT - -

      https://github.com/TooTallNate/node-http-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +        
      +
      +
    384. +
    385. +
      + http-proxy-agent 4.0.1 - MIT +

      + https://github.com/TooTallNate/node-http-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3963,17 +4601,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    386. -
    387. -
      - - http-proxy-agent 5.0.0 - MIT - -

      https://github.com/TooTallNate/node-http-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +        
      +
      +
    388. +
    389. +
      + http-proxy-agent 5.0.0 - MIT +

      + https://github.com/TooTallNate/node-http-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -3983,17 +4630,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    390. -
    391. -
      - - https-proxy-agent 5.0.0 - MIT - -

      https://github.com/TooTallNate/node-https-proxy-agent#readme

      -
      • Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
      -
      +        
      +
      +
    392. +
    393. +
      + https-proxy-agent 5.0.0 - MIT +

      + https://github.com/TooTallNate/node-https-proxy-agent#readme +

      +
        +
      • + Copyright (c) 2013 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4003,17 +4659,25 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    394. -
    395. -
      - - indexable-array 0.7.0 - MIT - -

      https://github.com/ozum/indexable-array

      -
      • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net>
      -
      +        
      +
      +
    396. +
    397. +
      + indexable-array 0.7.0 - MIT +

      + https://github.com/ozum/indexable-array +

      +
        +
      • + Copyright (c) 2021 Ozum Eldogan + <ozum@ozum.net> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net>
      @@ -4036,18 +4700,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    398. -
    399. -
      - - inflection 1.12.0 - MIT - -

      https://github.com/dreamerslab/node.inflection#readme

      -
      • Copyright (c) 2011
      • -
      • Copyright (c) 2011 Ben Lin <ben@dreamerslab.com>
      -
      +        
      +
      +
    400. +
    401. +
      + inflection 1.12.0 - MIT +

      + https://github.com/dreamerslab/node.inflection#readme +

      +
        +
      • Copyright (c) 2011
      • +
      • + Copyright (c) 2011 Ben Lin + <ben@dreamerslab.com> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4057,17 +4730,25 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    402. -
    403. -
      - - isarray 1.0.0 - MIT - -

      https://github.com/juliangruber/isarray

      -
      • Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
      -
      +        
      +
      +
    404. +
    405. +
      + isarray 1.0.0 - MIT +

      + https://github.com/juliangruber/isarray +

      +
        +
      • + Copyright (c) 2013 Julian Gruber + <julian@juliangruber.com> +
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4077,17 +4758,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    406. -
    407. -
      - - is-docker 2.2.1 - MIT - -

      https://github.com/sindresorhus/is-docker#readme

      -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      -
      +        
      +
      +
    408. +
    409. +
      + is-docker 2.2.1 - MIT +

      + https://github.com/sindresorhus/is-docker#readme +

      +
        +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> + (https://sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      @@ -4098,17 +4789,25 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    410. -
    411. -
      - - is-wsl 2.2.0 - MIT - -

      https://github.com/sindresorhus/is-wsl#readme

      -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      -
      +        
      +
      +
    412. +
    413. +
      + is-wsl 2.2.0 - MIT +

      + https://github.com/sindresorhus/is-wsl#readme +

      +
        +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> (sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
      @@ -4119,19 +4818,22 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    414. -
    415. -
      - - json5 2.2.3 - MIT - -

      http://json5.org/

      -
      • (c) 2019 Denis Pushkarev
      • -
      • copyright (c) 2019 Denis Pushkarev
      • -
      • Copyright (c) 2012-2018 Aseem Kishore, and others
      -
      +        
      +
      +
    416. +
    417. +
      + json5 2.2.3 - MIT +

      http://json5.org/

      +
        +
      • (c) 2019 Denis Pushkarev
      • +
      • copyright (c) 2019 Denis Pushkarev
      • +
      • + Copyright (c) 2012-2018 Aseem Kishore, and others +
      • +
      +
               MIT License
       
       Copyright (c) 2012-2018 Aseem Kishore, and [others].
      @@ -4156,19 +4858,25 @@ 

      NOTICES AND INFORMATION

      [others]: https://github.com/json5/json5/contributors -
      -
      -
    418. -
    419. -
      - - jsonc-parser 2.2.1 - MIT - -

      https://github.com/microsoft/node-jsonc-parser#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright 2018, Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    420. +
    421. +
      + jsonc-parser 2.2.1 - MIT +

      + https://github.com/microsoft/node-jsonc-parser#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright 2018, Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -4191,18 +4899,30 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    422. -
    423. -
      - - jsonfile 4.0.0 - MIT - -

      https://github.com/jprichardson/node-jsonfile#readme

      -
      • Copyright 2012-2016, JP Richardson <jprichardson@gmail.com>
      • -
      • Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
      -
      +        
      +
      +
    424. +
    425. +
      + jsonfile 4.0.0 - MIT +

      + https://github.com/jprichardson/node-jsonfile#readme +

      +
        +
      • + Copyright 2012-2016, JP Richardson + <jprichardson@gmail.com> +
      • +
      • + Copyright (c) 2012-2015, JP Richardson + <jprichardson@gmail.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
      @@ -4219,18 +4939,23 @@ 

      NOTICES AND INFORMATION

      OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    426. -
    427. -
      - - jsonparse 1.3.1 - MIT - -

      https://github.com/creationix/jsonparse#readme

      -
      • Copyright (c) 2012 Tim Caswell
      • -
      • Copyright (c) 2011-2012 Tim Caswell
      -
      +        
      +
      +
    428. +
    429. +
      + jsonparse 1.3.1 - MIT +

      + https://github.com/creationix/jsonparse#readme +

      +
        +
      • Copyright (c) 2012 Tim Caswell
      • +
      • Copyright (c) 2011-2012 Tim Caswell
      • +
      +
               The MIT License
       
       Copyright (c) 2012 Tim Caswell
      @@ -4256,19 +4981,30 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    430. -
    431. -
      - - lodash.get 4.4.2 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +        
      +
      +
    432. +
    433. +
      + lodash.get 4.4.2 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4317,19 +5053,30 @@ 

      NOTICES AND INFORMATION

      licenses; we recommend you read them, as their terms may differ from the terms above. -
      -
      -
    434. -
    435. -
      - - lodash.isfunction 3.0.9 - MIT - -

      https://lodash.com/

      -
      • Copyright JS Foundation and other contributors <https://js.foundation/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +        
      +
      +
    436. +
    437. +
      + lodash.isfunction 3.0.9 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright JS Foundation and other contributors + <https://js.foundation/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright JS Foundation and other contributors <https://js.foundation/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4378,19 +5125,30 @@ 

      NOTICES AND INFORMATION

      licenses; we recommend you read them, as their terms may differ from the terms above. -
      -
      -
    438. -
    439. -
      - - lodash.set 4.3.2 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +        
      +
      +
    440. +
    441. +
      + lodash.set 4.3.2 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4439,19 +5197,30 @@ 

      NOTICES AND INFORMATION

      licenses; we recommend you read them, as their terms may differ from the terms above. -
      -
      -
    442. -
    443. -
      - - lodash.transform 4.6.0 - MIT - -

      https://lodash.com/

      -
      • Copyright jQuery Foundation and other contributors <https://jquery.org/>
      • -
      • Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
      -
      +        
      +
      +
    444. +
    445. +
      + lodash.transform 4.6.0 - MIT +

      https://lodash.com/

      +
        +
      • + Copyright jQuery Foundation and other contributors + <https://jquery.org/> +
      • +
      • + Copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors +
      • +
      • + copyright Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors + <http://underscorejs.org/> +
      • +
      +
               Copyright jQuery Foundation and other contributors <https://jquery.org/>
       
       Based on Underscore.js, copyright Jeremy Ashkenas,
      @@ -4500,17 +5269,22 @@ 

      NOTICES AND INFORMATION

      licenses; we recommend you read them, as their terms may differ from the terms above. -
      -
      -
    446. -
    447. -
      - - map-stream 0.0.7 - MIT - -

      http://github.com/dominictarr/map-stream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +        
      +
      +
    448. +
    449. +
      + map-stream 0.0.7 - MIT +

      + http://github.com/dominictarr/map-stream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2011 Dominic Tarr
      @@ -4536,17 +5310,22 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    450. -
    451. -
      - - memory-pager 1.5.0 - MIT - -

      https://github.com/mafintosh/memory-pager

      -
      • Copyright (c) 2017 Mathias Buus
      -
      +        
      +
      +
    452. +
    453. +
      + memory-pager 1.5.0 - MIT +

      + https://github.com/mafintosh/memory-pager +

      +
        +
      • Copyright (c) 2017 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2017 Mathias Buus
      @@ -4569,18 +5348,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    454. -
    455. -
      - - mime-db 1.44.0 - MIT - -

      https://github.com/jshttp/mime-db#readme

      -
      • Copyright (c) 2014 Jonathan Ong
      • -
      • Copyright (c) 2014 Jonathan Ong me@jongleberry.com
      -
      +        
      +
      +
    456. +
    457. +
      + mime-db 1.44.0 - MIT +

      + https://github.com/jshttp/mime-db#readme +

      +
        +
      • Copyright (c) 2014 Jonathan Ong
      • +
      • + Copyright (c) 2014 Jonathan Ong me@jongleberry.com +
      • +
      +
               
       The MIT License (MIT)
       
      @@ -4604,20 +5390,31 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    458. -
    459. -
      - - mime-types 2.1.27 - MIT - -

      https://github.com/jshttp/mime-types#readme

      -
      • Copyright (c) 2014 Jonathan Ong
      • -
      • Copyright (c) 2015 Douglas Christopher Wilson
      • -
      • Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
      • -
      • Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
      -
      +        
      +
      +
    460. +
    461. +
      + mime-types 2.1.27 - MIT +

      + https://github.com/jshttp/mime-types#readme +

      +
        +
      • Copyright (c) 2014 Jonathan Ong
      • +
      • Copyright (c) 2015 Douglas Christopher Wilson
      • +
      • + Copyright (c) 2014 Jonathan Ong + <me@jongleberry.com> +
      • +
      • + Copyright (c) 2015 Douglas Christopher Wilson + <doug@somethingdoug.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
      @@ -4642,17 +5439,20 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    462. -
    463. -
      - - minimist 1.2.6 - MIT - -

      https://github.com/substack/minimist

      - -
      +        
      +
      +
    464. +
    465. +
      + minimist 1.2.6 - MIT +

      + https://github.com/substack/minimist +

      + +
               This software is released under the MIT license:
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of
      @@ -4672,17 +5472,24 @@ 

      NOTICES AND INFORMATION

      IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    466. -
    467. -
      - - moment 2.29.4 - MIT - -

      https://momentjs.com/

      -
      • Copyright (c) JS Foundation and other contributors
      -
      +        
      +
      +
    468. +
    469. +
      + moment 2.29.4 - MIT +

      + https://momentjs.com/ +

      +
        +
      • + Copyright (c) JS Foundation and other contributors +
      • +
      +
               Copyright (c) JS Foundation and other contributors
       
       Permission is hereby granted, free of charge, to any person
      @@ -4706,17 +5513,22 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    470. -
    471. -
      - - ms 2.1.2 - MIT - -

      https://github.com/zeit/ms#readme

      -
      • Copyright (c) 2016 Zeit, Inc.
      -
      +        
      +
      +
    472. +
    473. +
      + ms 2.1.2 - MIT +

      + https://github.com/zeit/ms#readme +

      +
        +
      • Copyright (c) 2016 Zeit, Inc.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Zeit, Inc.
      @@ -4739,17 +5551,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    474. -
    475. -
      - - nearley 2.20.1 - MIT - -

      https://github.com/hardmath123/nearley#readme

      -
      • Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
      -
      +        
      +
      +
    476. +
    477. +
      + nearley 2.20.1 - MIT +

      + https://github.com/hardmath123/nearley#readme +

      +
        +
      • + Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 + Kartik Chandra, Tim Radvan +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019 Kartik Chandra, Tim Radvan
      @@ -4772,17 +5592,21 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    478. -
    479. -
      - - node-abort-controller 3.0.1 - MIT - -

      https://github.com/southpolesteve/node-abort-controller#readme

      - -
      +        
      +
      +
    480. +
    481. +
      + node-abort-controller 3.0.1 - MIT +

      + https://github.com/southpolesteve/node-abort-controller#readme +

      + +
               MIT License
       
       Copyright (c) 2019 Steve Faulkner
      @@ -4805,17 +5629,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    482. -
    483. -
      - - node-fetch 2.6.7 - MIT - -

      https://github.com/bitinn/node-fetch

      -
      • Copyright (c) 2016 David Frank
      -
      +        
      +
      +
    484. +
    485. +
      + node-fetch 2.6.7 - MIT +

      + https://github.com/bitinn/node-fetch +

      +
        +
      • Copyright (c) 2016 David Frank
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 David Frank
      @@ -4839,21 +5668,42 @@ 

      NOTICES AND INFORMATION

      SOFTWARE. -
      -
      -
    486. -
    487. -
      - - open 8.4.2 - MIT - -

      https://github.com/sindresorhus/open#readme

      -
      • Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
      • -
      • Copyright 2006, Jeremy White <jwhite@codeweavers.com>
      • -
      • Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
      • -
      • Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
      • -
      • Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      -
      +        
      +
      +
    488. +
    489. +
      + open 8.4.2 - MIT +

      + https://github.com/sindresorhus/open#readme +

      +
        +
      • + Copyright 2006, Kevin Krammer + <kevin.krammer@gmx.at> +
      • +
      • + Copyright 2006, Jeremy White + <jwhite@codeweavers.com> +
      • +
      • + Copyright 2009-2010, Fathi Boudra + <fabo@freedesktop.org> +
      • +
      • + Copyright 2009-2010, Rex Dieter + <rdieter@fedoraproject.org> +
      • +
      • + Copyright (c) Sindre Sorhus + <sindresorhus@gmail.com> + (https://sindresorhus.com) +
      • +
      +
               MIT License
       
       Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
      @@ -4864,17 +5714,22 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    490. -
    491. -
      - - packet-reader 1.0.0 - MIT - -

      https://github.com/brianc/node-packet-reader

      -
      • Copyright 2015 Brian M. Carlson
      -
      +        
      +
      +
    492. +
    493. +
      + packet-reader 1.0.0 - MIT +

      + https://github.com/brianc/node-packet-reader +

      +
        +
      • Copyright 2015 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -4884,17 +5739,20 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    494. -
    495. -
      - - parseley 0.7.0 - MIT - -

      https://github.com/mxxii/parseley

      - -
      +        
      +
      +
    496. +
    497. +
      + parseley 0.7.0 - MIT +

      + https://github.com/mxxii/parseley +

      + +
               MIT License
       
       Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      @@ -4917,18 +5775,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    498. -
    499. -
      - - performance-now 2.1.0 - MIT - -

      https://github.com/braveg1rl/performance-now

      -
      • Copyright (c) 2013 Braveg1rl
      • -
      • Copyright (c) 2017 Braveg1rl
      -
      +        
      +
      +
    500. +
    501. +
      + performance-now 2.1.0 - MIT +

      + https://github.com/braveg1rl/performance-now +

      +
        +
      • Copyright (c) 2013 Braveg1rl
      • +
      • Copyright (c) 2017 Braveg1rl
      • +
      +
               Copyright (c) 2013 Braveg1rl
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      @@ -4936,18 +5799,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    502. -
    503. -
      - - pg 8.11.2 - MIT - -

      https://github.com/brianc/node-postgres

      -
      • Copyright (c) 2010 - 2021 Brian Carlson
      • -
      • Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com)
      -
      +        
      +
      +
    504. +
    505. +
      + pg 8.11.2 - MIT +

      + https://github.com/brianc/node-postgres +

      +
        +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      • + Copyright (c) 2010-2020 Brian Carlson + (brian.m.carlson@gmail.com) +
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -4970,18 +5841,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    506. -
    507. -
      - - pg-cloudflare 1.1.1 - MIT - -

      https://github.com/brianc/node-postgres#readme

      -
      • Copyright (c) 2023 Brian M. Carlson
      • -
      • Copyright (c) 2010 - 2021 Brian Carlson
      -
      +        
      +
      +
    508. +
    509. +
      + pg-cloudflare 1.1.1 - MIT +

      + https://github.com/brianc/node-postgres#readme +

      +
        +
      • Copyright (c) 2023 Brian M. Carlson
      • +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -5004,18 +5880,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    510. -
    511. -
      - - pg-connection-string 2.6.2 - MIT - -

      https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string

      -
      • Copyright (c) 2014 Iced Development
      • -
      • Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
      -
      +        
      +
      +
    512. +
    513. +
      + pg-connection-string 2.6.2 - MIT +

      + https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string +

      +
        +
      • Copyright (c) 2014 Iced Development
      • +
      • + Copyright (c) 2010-2014 Brian Carlson + (brian.m.carlson@gmail.com) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2014 Iced Development
      @@ -5037,17 +5922,22 @@ 

      NOTICES AND INFORMATION

      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    514. -
    515. -
      - - pgpass 1.0.2 - MIT - -

      https://github.com/hoegaarden/pgpass#readme

      -
      • Copyright (c) 2013-2016 Hannes Horl
      -
      +        
      +
      +
    516. +
    517. +
      + pgpass 1.0.2 - MIT +

      + https://github.com/hoegaarden/pgpass#readme +

      +
        +
      • Copyright (c) 2013-2016 Hannes Horl
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5057,18 +5947,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    518. -
    519. -
      - - pg-pool 3.6.1 - MIT - -

      https://github.com/brianc/node-pg-pool#readme

      -
      • Copyright (c) 2016 Brian M. Carlson
      • -
      • Copyright (c) 2017 Brian M. Carlson
      -
      +        
      +
      +
    520. +
    521. +
      + pg-pool 3.6.1 - MIT +

      + https://github.com/brianc/node-pg-pool#readme +

      +
        +
      • Copyright (c) 2016 Brian M. Carlson
      • +
      • Copyright (c) 2017 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2017 Brian M. Carlson
      @@ -5091,17 +5986,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    522. -
    523. -
      - - pg-protocol 1.6.0 - MIT - -

      https://github.com/brianc/node-postgres#readme

      -
      • Copyright (c) 2010 - 2021 Brian Carlson
      -
      +        
      +
      +
    524. +
    525. +
      + pg-protocol 1.6.0 - MIT +

      + https://github.com/brianc/node-postgres#readme +

      +
        +
      • Copyright (c) 2010 - 2021 Brian Carlson
      • +
      +
               MIT License
       
       Copyright (c) 2010 - 2021 Brian Carlson
      @@ -5124,17 +6024,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    526. -
    527. -
      - - pg-structure 7.15.0 - MIT - -

      https://www.pg-structure.com/

      -
      • Copyright (c) 2021 Ozum Eldogan <ozum@ozum.net> (https://www.ozum.net/)
      -
      +        
      +
      +
    528. +
    529. +
      + pg-structure 7.15.0 - MIT +

      + https://www.pg-structure.com/ +

      +
        +
      • + Copyright (c) 2021 Ozum Eldogan + <ozum@ozum.net> (https://www.ozum.net/) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2021 Özüm Eldoğan <ozum@ozum.net> (https://www.ozum.net/)
      @@ -5157,17 +6065,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    530. -
    531. -
      - - pg-types 2.2.0 - MIT - -

      https://github.com/brianc/node-pg-types

      -
      • Copyright (c) 2014 Brian M. Carlson
      -
      +        
      +
      +
    532. +
    533. +
      + pg-types 2.2.0 - MIT +

      + https://github.com/brianc/node-pg-types +

      +
        +
      • Copyright (c) 2014 Brian M. Carlson
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5177,18 +6090,27 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    534. -
    535. -
      - - postgres-array 2.0.0 - MIT - -

      https://github.com/bendrucker/postgres-array#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +        
      +
      +
    536. +
    537. +
      + postgres-array 2.0.0 - MIT +

      + https://github.com/bendrucker/postgres-array#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5211,18 +6133,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    538. -
    539. -
      - - postgres-bytea 1.0.0 - MIT - -

      https://github.com/bendrucker/postgres-bytea#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +        
      +
      +
    540. +
    541. +
      + postgres-bytea 1.0.0 - MIT +

      + https://github.com/bendrucker/postgres-bytea#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5245,18 +6176,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    542. -
    543. -
      - - postgres-date 1.0.6 - MIT - -

      https://github.com/bendrucker/postgres-date#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +        
      +
      +
    544. +
    545. +
      + postgres-date 1.0.6 - MIT +

      + https://github.com/bendrucker/postgres-date#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5279,18 +6219,27 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    546. -
    547. -
      - - postgres-interval 1.2.0 - MIT - -

      https://github.com/bendrucker/postgres-interval#readme

      -
      • (c) Ben Drucker (http://bendrucker.me)
      • -
      • Copyright (c) Ben Drucker <bvdrucker@gmail.com>
      -
      +        
      +
      +
    548. +
    549. +
      + postgres-interval 1.2.0 - MIT +

      + https://github.com/bendrucker/postgres-interval#readme +

      +
        +
      • (c) Ben Drucker (http://bendrucker.me)
      • +
      • + Copyright (c) Ben Drucker + <bvdrucker@gmail.com> +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
      @@ -5313,17 +6262,21 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    550. -
    551. -
      - - priorityqueuejs 1.0.0 - MIT - -

      https://github.com/janogonzalez/priorityqueuejs

      - -
      +        
      +
      +
    552. +
    553. +
      + priorityqueuejs 1.0.0 - MIT +

      + https://github.com/janogonzalez/priorityqueuejs +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5333,17 +6286,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    554. -
    555. -
      - - process-nextick-args 2.0.1 - MIT - -

      https://github.com/calvinmetcalf/process-nextick-args

      -
      • Copyright (c) 2015 Calvin Metcalf
      -
      +        
      +
      +
    556. +
    557. +
      + process-nextick-args 2.0.1 - MIT +

      + https://github.com/calvinmetcalf/process-nextick-args +

      +
        +
      • Copyright (c) 2015 Calvin Metcalf
      • +
      +
               # Copyright (c) 2015 Calvin Metcalf
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5364,17 +6323,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** -
      -
      -
    558. -
    559. -
      - - raf 3.4.1 - MIT - -

      https://github.com/chrisdickinson/raf#readme

      -
      • Copyright 2013 Chris Dickinson <chris@neversaw.us>
      -
      +        
      +
      +
    560. +
    561. +
      + raf 3.4.1 - MIT +

      + https://github.com/chrisdickinson/raf#readme +

      +
        +
      • + Copyright 2013 Chris Dickinson + <chris@neversaw.us> +
      • +
      +
               Copyright 2013 Chris Dickinson <chris@neversaw.us>
       
       Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
      @@ -5383,17 +6350,22 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    562. -
    563. -
      - - randexp 0.4.6 - MIT - -

      http://fent.github.io/randexp.js/

      -
      • Copyright (c) 2011 by Roly Fentanes
      -
      +        
      +
      +
    564. +
    565. +
      + randexp 0.4.6 - MIT +

      + http://fent.github.io/randexp.js/ +

      +
        +
      • Copyright (c) 2011 by Roly Fentanes
      • +
      +
               Copyright (C) 2011 by Roly Fentanes
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5414,17 +6386,25 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    566. -
    567. -
      - - readable-stream 2.3.7 - MIT - -

      https://github.com/nodejs/readable-stream#readme

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +        
      +
      +
    568. +
    569. +
      + readable-stream 2.3.7 - MIT +

      + https://github.com/nodejs/readable-stream#readme +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Node.js is licensed for use as follows:
       
       """
      @@ -5473,17 +6453,22 @@ 

      NOTICES AND INFORMATION

      IN THE SOFTWARE. """ -
      -
      -
    570. -
    571. -
      - - ret 0.1.15 - MIT - -

      https://github.com/fent/ret.js#readme

      -
      • Copyright (c) 2011 by Roly Fentanes
      -
      +        
      +
      +
    572. +
    573. +
      + ret 0.1.15 - MIT +

      + https://github.com/fent/ret.js#readme +

      +
        +
      • Copyright (c) 2011 by Roly Fentanes
      • +
      +
               Copyright (C) 2011 by Roly Fentanes
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -5504,18 +6489,26 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    574. -
    575. -
      - - safe-buffer 5.1.2 - MIT - -

      https://github.com/feross/safe-buffer

      -
      • Copyright (c) Feross Aboukhadijeh
      • -
      • Copyright (c) Feross Aboukhadijeh (http://feross.org)
      -
      +        
      +
      +
    576. +
    577. +
      + safe-buffer 5.1.2 - MIT +

      + https://github.com/feross/safe-buffer +

      +
        +
      • Copyright (c) Feross Aboukhadijeh
      • +
      • + Copyright (c) Feross Aboukhadijeh + (http://feross.org) +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Feross Aboukhadijeh
      @@ -5538,18 +6531,24 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    578. -
    579. -
      - - saslprep 1.0.3 - MIT - -

      https://github.com/reklatsmasters/saslprep#readme

      -
      • (c) Dmitriy Tsvettsikh
      • -
      • Copyright (c) 2014 Dmitry Tsvettsikh
      -
      +        
      +
      +
    580. +
    581. +
      + saslprep 1.0.3 - MIT +

      + https://github.com/reklatsmasters/saslprep#readme +

      +
        +
      • (c) Dmitriy Tsvettsikh
      • +
      • Copyright (c) 2014 Dmitry Tsvettsikh
      • +
      +
               Copyright (c) 2014 Dmitry Tsvettsikh
       
       Permission is hereby granted, free of charge, to any person
      @@ -5572,17 +6571,20 @@ 

      NOTICES AND INFORMATION

      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    582. -
    583. -
      - - selderee 0.6.0 - MIT - -

      https://github.com/mxxii/selderee

      - -
      +        
      +
      +
    584. +
    585. +
      + selderee 0.6.0 - MIT +

      + https://github.com/mxxii/selderee +

      + +
               MIT License
       
       Copyright (c) 2021 KillyMXI <killy@mxii.eu.org>
      @@ -5605,17 +6607,20 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    586. -
    587. -
      - - semaphore 1.0.5 - MIT - -

      https://github.com/abrkn/semaphore.js

      - -
      +        
      +
      +
    588. +
    589. +
      + semaphore 1.0.5 - MIT +

      + https://github.com/abrkn/semaphore.js +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5625,17 +6630,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    590. -
    591. -
      - - sorted-array-functions 1.3.0 - MIT - -

      https://github.com/mafintosh/sorted-array-functions

      -
      • Copyright (c) 2016 Mathias Buus
      -
      +        
      +
      +
    592. +
    593. +
      + sorted-array-functions 1.3.0 - MIT +

      + https://github.com/mafintosh/sorted-array-functions +

      +
        +
      • Copyright (c) 2016 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Mathias Buus
      @@ -5658,17 +6669,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    594. -
    595. -
      - - sparse-bitfield 3.0.3 - MIT - -

      https://github.com/mafintosh/sparse-bitfield

      -
      • Copyright (c) 2016 Mathias Buus
      -
      +        
      +
      +
    596. +
    597. +
      + sparse-bitfield 3.0.3 - MIT +

      + https://github.com/mafintosh/sparse-bitfield +

      +
        +
      • Copyright (c) 2016 Mathias Buus
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2016 Mathias Buus
      @@ -5691,17 +6707,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    598. -
    599. -
      - - split 1.0.1 - MIT - -

      http://github.com/dominictarr/split

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +        
      +
      +
    600. +
    601. +
      + split 1.0.1 - MIT +

      + http://github.com/dominictarr/split +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               Copyright (c) 2011 Dominic Tarr
       
       Permission is hereby granted, free of charge, 
      @@ -5724,17 +6745,22 @@ 

      NOTICES AND INFORMATION

      ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    602. -
    603. -
      - - stream-combiner 0.2.2 - MIT - -

      https://github.com/dominictarr/stream-combiner

      -
      • Copyright (c) 2012 Dominic Tarr
      -
      +        
      +
      +
    604. +
    605. +
      + stream-combiner 0.2.2 - MIT +

      + https://github.com/dominictarr/stream-combiner +

      +
        +
      • Copyright (c) 2012 Dominic Tarr
      • +
      +
               Copyright (c) 2012 'Dominic Tarr'
       
       Permission is hereby granted, free of charge, 
      @@ -5758,17 +6784,24 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    606. -
    607. -
      - - string_decoder 1.1.1 - MIT - -

      https://github.com/nodejs/string_decoder

      -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +        
      +
      +
    608. +
    609. +
      + string_decoder 1.1.1 - MIT +

      + https://github.com/nodejs/string_decoder +

      +
        +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               Node.js is licensed for use as follows:
       
       """
      @@ -5818,17 +6851,15 @@ 

      NOTICES AND INFORMATION

      """ -
      -
      -
    610. -
    611. -
      - - tas-client 0.1.45 - MIT - - - -
      +        
      +
      +
    612. +
    613. +
      + tas-client 0.1.45 - MIT + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5838,17 +6869,22 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    614. -
    615. -
      - - through 2.3.8 - MIT - -

      https://github.com/dominictarr/through

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +        
      +
      +
    616. +
    617. +
      + through 2.3.8 - MIT +

      + https://github.com/dominictarr/through +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -5874,17 +6910,20 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    618. -
    619. -
      - - tr46 0.0.3 - MIT - -

      https://github.com/Sebmaster/tr46.js#readme

      - -
      +        
      +
      +
    620. +
    621. +
      + tr46 0.0.3 - MIT +

      + https://github.com/Sebmaster/tr46.js#readme +

      + +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -5894,17 +6933,22 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    622. -
    623. -
      - - tunnel 0.0.6 - MIT - -

      https://github.com/koichik/node-tunnel/

      -
      • Copyright (c) 2012 Koichi Kobayashi
      -
      +        
      +
      +
    624. +
    625. +
      + tunnel 0.0.6 - MIT +

      + https://github.com/koichik/node-tunnel/ +

      +
        +
      • Copyright (c) 2012 Koichi Kobayashi
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2012 Koichi Kobayashi
      @@ -5927,18 +6971,30 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    626. -
    627. -
      - - underscore 1.12.1 - MIT - -

      https://underscorejs.org/

      -
      • Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
      • -
      • (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore
      -
      +        
      +
      +
    628. +
    629. +
      + underscore 1.12.1 - MIT +

      + https://underscorejs.org/ +

      +
        +
      • + Copyright (c) 2009-2020 Jeremy Ashkenas, + DocumentCloud and Investigative Reporters & + Editors +
      • +
      • + (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and + Investigative Reporters & Editors Underscore +
      • +
      +
               Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative
       Reporters & Editors
       
      @@ -5963,17 +7019,25 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    630. -
    631. -
      - - universalify 0.1.2 - MIT - -

      https://github.com/RyanZim/universalify#readme

      -
      • Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
      -
      +        
      +
      +
    632. +
    633. +
      + universalify 0.1.2 - MIT +

      + https://github.com/RyanZim/universalify#readme +

      +
        +
      • + Copyright (c) 2017, Ryan Zimmerman + <opensrc@ryanzim.com> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
      @@ -5995,17 +7059,25 @@ 

      NOTICES AND INFORMATION

      IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    634. -
    635. -
      - - util-deprecate 1.0.2 - MIT - -

      https://github.com/TooTallNate/util-deprecate

      -
      • Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
      -
      +        
      +
      +
    636. +
    637. +
      + util-deprecate 1.0.2 - MIT +

      + https://github.com/TooTallNate/util-deprecate +

      +
        +
      • + Copyright (c) 2014 Nathan Rajlich + <nathan@tootallnate.net> +
      • +
      +
               (The MIT License)
       
       Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
      @@ -6031,19 +7103,33 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    638. -
    639. -
      - - uuid 3.4.0 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2016 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +        
      +
      +
    640. +
    641. +
      + uuid 3.4.0 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2016 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2016 Robert Kieffer and other contributors
      @@ -6066,19 +7152,33 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    642. -
    643. -
      - - uuid 8.3.2 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2020 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +        
      +
      +
    644. +
    645. +
      + uuid 8.3.2 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2020 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2020 Robert Kieffer and other contributors
      @@ -6089,19 +7189,33 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    646. -
    647. -
      - - uuid 9.0.1 - MIT - -

      https://github.com/uuidjs/uuid#readme

      -
      • Copyright 2011, Sebastian Tschan https://blueimp.net
      • -
      • Copyright (c) 2010-2020 Robert Kieffer and other contributors
      • -
      • Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet
      -
      +        
      +
      +
    648. +
    649. +
      + uuid 9.0.1 - MIT +

      + https://github.com/uuidjs/uuid#readme +

      +
        +
      • + Copyright 2011, Sebastian Tschan https://blueimp.net +
      • +
      • + Copyright (c) 2010-2020 Robert Kieffer and other + contributors +
      • +
      • + Copyright (c) Paul Johnston 1999 - 2009 Other + contributors Greg Holt, Andrew Kepert, Ydnar, + Lostinet +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2010-2020 Robert Kieffer and other contributors
      @@ -6112,18 +7226,24 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    650. -
    651. -
      - - vscode-json-languageservice 3.5.2 - MIT - -

      https://github.com/Microsoft/vscode-json-languageservice#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    652. +
    653. +
      + vscode-json-languageservice 3.5.2 - MIT +

      + https://github.com/Microsoft/vscode-json-languageservice#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6146,17 +7266,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    654. -
    655. -
      - - vscode-jsonrpc 5.0.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    656. +
    657. +
      + vscode-jsonrpc 5.0.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6169,18 +7295,26 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    658. -
    659. -
      - - vscode-languageclient 6.1.3 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      • -
      • Copyright (c) Isaac Z. Schlueter and Contributors
      -
      +        
      +
      +
    660. +
    661. +
      + vscode-languageclient 6.1.3 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      • + Copyright (c) Isaac Z. Schlueter and Contributors +
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6193,17 +7327,23 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    662. -
    663. -
      - - vscode-languageserver 6.1.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    664. +
    665. +
      + vscode-languageserver 6.1.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6216,18 +7356,26 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    666. -
    667. -
      - - vscode-languageserver-protocol 3.15.3 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) TypeFox and others.
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    668. +
    669. +
      + + vscode-languageserver-protocol 3.15.3 - MIT + +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) TypeFox and others.
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6240,17 +7388,25 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    670. -
    671. -
      - - vscode-languageserver-textdocument 1.0.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    672. +
    673. +
      + + vscode-languageserver-textdocument 1.0.1 - MIT + +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6263,17 +7419,23 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    674. -
    675. -
      - - vscode-languageserver-types 3.15.1 - MIT - -

      https://github.com/Microsoft/vscode-languageserver-node#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    676. +
    677. +
      + vscode-languageserver-types 3.15.1 - MIT +

      + https://github.com/Microsoft/vscode-languageserver-node#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               Copyright (c) Microsoft Corporation
       
       All rights reserved.
      @@ -6286,17 +7448,22 @@ 

      NOTICES AND INFORMATION

      THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    678. -
    679. -
      - - vscode-nls 4.1.2 - MIT - -

      https://github.com/Microsoft/vscode-nls#readme

      -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    680. +
    681. +
      + vscode-nls 4.1.2 - MIT +

      + https://github.com/Microsoft/vscode-nls#readme +

      +
        +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft Corporation
      @@ -6315,17 +7482,18 @@ 

      NOTICES AND INFORMATION

      BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    682. -
    683. -
      - - vscode-tas-client 0.1.47 - MIT - - -
      • Copyright (c) Microsoft Corporation
      -
      +        
      +
      +
    684. +
    685. +
      + vscode-tas-client 0.1.47 - MIT + +
        +
      • Copyright (c) Microsoft Corporation
      • +
      +
               MIT License
       
       Copyright (c) <year> <copyright holders>
      @@ -6335,18 +7503,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    686. -
    687. -
      - - vscode-uri 1.0.8 - MIT - -

      https://github.com/Microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    688. +
    689. +
      + vscode-uri 1.0.8 - MIT +

      + https://github.com/Microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6356,18 +7529,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    690. -
    691. -
      - - vscode-uri 2.1.2 - MIT - -

      https://github.com/Microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation.
      -
      +        
      +
      +
    692. +
    693. +
      + vscode-uri 2.1.2 - MIT +

      + https://github.com/Microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation.
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6377,19 +7555,26 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    694. -
    695. -
      - - vscode-uri 3.0.7 - MIT - -

      https://github.com/microsoft/vscode-uri#readme

      -
      • Copyright (c) Microsoft
      • -
      • Copyright (c) Microsoft Corporation
      • -
      • Copyright Joyent, Inc. and other Node contributors
      -
      +        
      +
      +
    696. +
    697. +
      + vscode-uri 3.0.7 - MIT +

      + https://github.com/microsoft/vscode-uri#readme +

      +
        +
      • Copyright (c) Microsoft
      • +
      • Copyright (c) Microsoft Corporation
      • +
      • + Copyright Joyent, Inc. and other Node contributors +
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) Microsoft
      @@ -6399,18 +7584,23 @@ 

      NOTICES AND INFORMATION

      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    698. -
    699. -
      - - whatwg-url 5.0.0 - MIT - -

      https://github.com/jsdom/whatwg-url#readme

      -
      • (c) extraPathPercentEncodeSet.has
      • -
      • Copyright (c) 2015-2016 Sebastian Mayr
      -
      +        
      +
      +
    700. +
    701. +
      + whatwg-url 5.0.0 - MIT +

      + https://github.com/jsdom/whatwg-url#readme +

      +
        +
      • (c) extraPathPercentEncodeSet.has
      • +
      • Copyright (c) 2015-2016 Sebastian Mayr
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2015–2016 Sebastian Mayr
      @@ -6433,17 +7623,23 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    702. -
    703. -
      - - xml2js 0.5.0 - MIT - -

      https://github.com/Leonidas-from-XIV/node-xml2js

      -
      • Copyright 2010, 2011, 2012, 2013
      -
      +        
      +
      +
    704. +
    705. +
      + xml2js 0.5.0 - MIT +

      + https://github.com/Leonidas-from-XIV/node-xml2js +

      +
        +
      • Copyright 2010, 2011, 2012, 2013
      • +
      +
               Copyright 2010, 2011, 2012, 2013. All rights reserved.
       
       Permission is hereby granted, free of charge, to any person obtaining a copy
      @@ -6464,17 +7660,22 @@ 

      NOTICES AND INFORMATION

      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    706. -
    707. -
      - - xmlbuilder 11.0.1 - MIT - -

      http://github.com/oozcitak/xmlbuilder-js

      -
      • Copyright (c) 2013 Ozgur Ozcitak
      -
      +        
      +
      +
    708. +
    709. +
      + xmlbuilder 11.0.1 - MIT +

      + http://github.com/oozcitak/xmlbuilder-js +

      +
        +
      • Copyright (c) 2013 Ozgur Ozcitak
      • +
      +
               The MIT License (MIT)
       
       Copyright (c) 2013 Ozgur Ozcitak
      @@ -6497,17 +7698,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    710. -
    711. -
      - - xtend 4.0.2 - MIT - -

      https://github.com/Raynos/xtend

      -
      • Copyright (c) 2012-2014 Raynos
      -
      +        
      +
      +
    712. +
    713. +
      + xtend 4.0.2 - MIT +

      + https://github.com/Raynos/xtend +

      +
        +
      • Copyright (c) 2012-2014 Raynos
      • +
      +
               The MIT License (MIT)
       Copyright (c) 2012-2014 Raynos.
       
      @@ -6529,17 +7735,22 @@ 

      NOTICES AND INFORMATION

      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    714. -
    715. -
      - - JSONStream 1.3.5 - MIT OR Apache-2.0 - -

      http://github.com/dominictarr/JSONStream

      -
      • Copyright (c) 2011 Dominic Tarr
      -
      +        
      +
      +
    716. +
    717. +
      + JSONStream 1.3.5 - MIT OR Apache-2.0 +

      + http://github.com/dominictarr/JSONStream +

      +
        +
      • Copyright (c) 2011 Dominic Tarr
      • +
      +
               The MIT License
       
       Copyright (c) 2011 Dominic Tarr
      @@ -6565,17 +7776,18 @@ 

      NOTICES AND INFORMATION

      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
      -
      -
    718. -
    719. -
      - - pause-stream 0.0.11 - MIT OR Apache-2.0 - - -
      • Copyright (c) 2013 Dominic Tarr
      -
      +        
      +
      +
    720. +
    721. +
      + pause-stream 0.0.11 - MIT OR Apache-2.0 + +
        +
      • Copyright (c) 2013 Dominic Tarr
      • +
      +
               Dual Licensed MIT and Apache 2
       
       The MIT License
      @@ -6807,9 +8019,10 @@ 

      NOTICES AND INFORMATION

      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -
      -
      -
    722. -
    - +
    +
    +
  2. +
+ diff --git a/README.md b/README.md index 7e1e0a465..f8518c0a5 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,77 @@ - # Azure Databases for VS Code (Preview) -[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) [![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) +[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-azuretools.vscode-cosmosdb.svg)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb) +[![Build Status](https://dev.azure.com/ms-azuretools/AzCode/_apis/build/status/vscode-cosmosdb)](https://dev.azure.com/ms-azuretools/AzCode/_build/latest?definitionId=7) -Browse and query your Azure databases both locally and in the cloud using [_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, Graph (Gremlin), and SQL (previously known as DocumentDB). +Browse and query your Azure databases both locally and in the cloud using +[_scrapbooks_](#mongo-scrapbooks) with rich Intellisense then connect to Azure +to manage your PostgreSQL and Cosmos DB databases with support for MongoDB, +Graph (Gremlin), and SQL (previously known as DocumentDB). ![Azure Databases Extension](resources/readme/overview.png) -> Sign up today for your free Azure account and receive 12 months of free popular services, $200 free credit and 25+ always free services 👉 [Start Free](https://azure.microsoft.com/free/open-source). +> Sign up today for your free Azure account and receive 12 months of free +> popular services, $200 free credit and 25+ always free services 👉 +> [Start Free](https://azure.microsoft.com/free/open-source). # Prerequisites -- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and use of the Mongo shell require installing [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). +- Some less-common commands in the Mongo [scrapbook](#mongo-scrapbooks) and + use of the Mongo shell require installing + [Mongo DB and Mongo shell](https://docs.mongodb.com/manual/installation/). # Features ## Azure Databases Explorer -- Create a database server by clicking the `+` button in the title -- View database servers and open directly in the portal -- View/Create/Delete databases, collections, graphs, stored procedures, documents, and queries -- Click on a document, stored procedure, or query to open in the editor -- Edit a document and persist changes to the cloud -- Attach a Mongo server by clicking the plug icon in the title +- Create a database server by clicking the `+` button in the title +- View database servers and open directly in the portal +- View/Create/Delete databases, collections, graphs, stored procedures, + documents, and queries +- Click on a document, stored procedure, or query to open in the editor +- Edit a document and persist changes to the cloud +- Attach a Mongo server by clicking the plug icon in the title ![Browse PostgreSQL, CosmosDB, and MongoDB databases](resources/readme/explorer.png) ## Mongo Scrapbooks + ### Run Mongo Commands with Rich Intellisense -- View your MongoDB database account by by clicking "Sign in to Azure..." in the Azure Resources explorer or using "Attach Database Account" to connect via a connection string -- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` if your mongo executable is not already on your system's PATH (many of the common commands have built-in support and do not require the Mongo shell to be installed - see [Prerequisites](#prerequisites)) -- Click on "New Mongo Scrapbook" in the tree title bar -- Click on "Connect to a database" to indicate which database to run the commands against -- Enter your commands and/or comments, eg: `db..find()` -- IntelliSense (auto-completions) will be provided -- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or `CTRL+"` (Windows and Linux) to execute the line with the cursor -- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` -- Save and re-use later -![Mongo Scrapbook](resources/readme/Scrapbook.gif) +- View your MongoDB database account by by clicking "Sign in to Azure..." in + the Azure Resources explorer or using "Attach Database Account" to connect + via a connection string +- Optionally configure the settings `mongo.shell.path` and `mongo.shell.args` + if your mongo executable is not already on your system's PATH (many of the + common commands have built-in support and do not require the Mongo shell to + be installed - see [Prerequisites](#prerequisites)) +- Click on "New Mongo Scrapbook" in the tree title bar +- Click on "Connect to a database" to indicate which database to run the + commands against +- Enter your commands and/or comments, eg: `db..find()` +- IntelliSense (auto-completions) will be provided +- Click on "Execute" above a command to execute it, or press `CMD+"` (Mac) or + `CTRL+"` (Windows and Linux) to execute the line with the cursor +- To run all commands, click on "Execute All", or press `CMD+:` or `Ctrl+:` +- Save and re-use later ![Mongo Scrapbook](resources/readme/Scrapbook.gif) ## Import into Cosmos DB -- You can now import documents from your workspace into CosmosDB. Use the context menu of a collection or a document file (json) to get started! -![Import documents](resources/readme/import_documents.gif) +- You can now import documents from your workspace into CosmosDB. Use the + context menu of a collection or a document file (json) to get started! + ![Import documents](resources/readme/import_documents.gif) ## Create an Azure Databases Server -1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure Resources explorer - > If you don't already have an Azure Account, click "Create a Free Azure Account" +1. Sign in to your Azure Account by clicking "Sign in to Azure..." in the Azure + Resources explorer + > If you don't already have an Azure Account, click "Create a Free Azure + > Account" 1. Select the 'plus' button to open the "Create Resource" menu ![Create resource](resources/readme/createResource.png) @@ -63,42 +82,82 @@ Browse and query your Azure databases both locally and in the cloud using [_scra ## Attach to the Cosmos DB Emulator -* Install and run the [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) on your local machine -* Right click 'Attached Database Accounts' and select 'Attach Emulator' +- Install and run the + [Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) + on your local machine +- Right click 'Attached Database Accounts' and select 'Attach Emulator' ![Attach Emulator](resources/readme/attachEmulator.png) ## Known Issues -- Azure no longer supports gremlin queries on pre-GA graph accounts. If you see the error "Could not find a valid gremlin endpoint for *graph*", then choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in the Overview tab. If it does not take the form of '...[graph-name].***gremlin***.cosmosdb.azure.com...', then you will need to create a new graph account using the Azure portal or the current version of the extension. -- Graphs are not currently supported with the emulator -- Viewing/editing tables is not currently supported -- Support for escapes in the scrapbooks is preliminary. We currently do not support escaped characters as is inside a string - the characters need to be double escaped. For example, newlines in the string should be '\\\\n' instead of '\\n' to be recognized correctly. If you find any issues with how the scrapbook handles escapes, please add to issue [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). +- Azure no longer supports gremlin queries on pre-GA graph accounts. If you + see the error "Could not find a valid gremlin endpoint for _graph_", then + choose "Open Portal" on the graph node and check the "Gremlin Endpoint" in + the Overview tab. If it does not take the form of + '...[graph-name].**_gremlin_**.cosmosdb.azure.com...', then you will need to + create a new graph account using the Azure portal or the current version of + the extension. +- Graphs are not currently supported with the emulator +- Viewing/editing tables is not currently supported +- Support for escapes in the scrapbooks is preliminary. We currently do not + support escaped characters as is inside a string - the characters need to be + double escaped. For example, newlines in the string should be '\\\\n' + instead of '\\n' to be recognized correctly. If you find any issues with how + the scrapbook handles escapes, please add to issue + [#937](https://github.com/Microsoft/vscode-cosmosdb/issues/937). # Contributing -There are several ways you can contribute to our [repo](https://github.com/Microsoft/vscode-cosmosdb): -* **Ideas, feature requests and bugs**: We are open to all ideas and we want to get rid of bugs! Use the [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to report a new issue, provide your ideas or contribute to existing threads. -* **Documentation**: Found a typo or strangely worded sentences? Submit a PR! -* **Code**: Contribute bug fixes, features or design changes: - * Clone the repository locally and open in VS Code. - * Run "Extensions: Show Recommended Extensions" from the [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and install all extensions listed under "Workspace Recommendations" - * Open the terminal (press CTRL+ \`) and run `npm install`. - * To build, press F1 and type in `Tasks: Run Build Task`. - * Debug: press F5 to start debugging the extension. +There are several ways you can contribute to our +[repo](https://github.com/Microsoft/vscode-cosmosdb): + +- **Ideas, feature requests and bugs**: We are open to all ideas and we want + to get rid of bugs! Use the + [Issues](https://github.com/Microsoft/vscode-cosmosdb/issues) section to + report a new issue, provide your ideas or contribute to existing threads. +- **Documentation**: Found a typo or strangely worded sentences? Submit a PR! +- **Code**: Contribute bug fixes, features or design changes: + - Clone the repository locally and open in VS Code. + - Run "Extensions: Show Recommended Extensions" from the + [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) + and install all extensions listed under "Workspace Recommendations" + - Open the terminal (press CTRL+ \`) and run + `npm install`. + - To build, press F1 and type in `Tasks: Run Build Task`. + - Debug: press F5 to start debugging the extension. ## Legal -Before we can accept your pull request you will need to sign a **Contribution License Agreement**. All you need to do is to submit a pull request, then the PR will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, `cla-signed`, `cla-already-signed`). If you already signed the agreement we will continue with reviewing the PR, otherwise system will tell you how you can sign the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. + +Before we can accept your pull request you will need to sign a **Contribution +License Agreement**. All you need to do is to submit a pull request, then the PR +will get appropriately labelled (e.g. `cla-required`, `cla-norequired`, +`cla-signed`, `cla-already-signed`). If you already signed the agreement we will +continue with reviewing the PR, otherwise system will tell you how you can sign +the CLA. Once you sign the CLA all future PR's will be labeled as `cla-signed`. ## Code of Conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the +[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any +additional questions or comments. # Telemetry -VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). + +VS Code collects usage data and sends it to Microsoft to help improve our +products and services. Read our +[privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) +to learn more. If you don’t wish to send usage data to Microsoft, you can set +the `telemetry.enableTelemetry` setting to `false`. Learn more in our +[FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). # License + [MIT](LICENSE.md) diff --git a/SECURITY.md b/SECURITY.md index 926b8ae40..1e9543683 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,33 +2,54 @@ ## Security -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). - -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +Microsoft takes the security of our software products and services seriously, +which includes all source code repositories managed through our GitHub +organizations, which include [Microsoft](https://github.com/Microsoft), +[Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), +[AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and +[our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned +repository that meets +[Microsoft's definition of a security vulnerability](), +please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). +Instead, please report them to the Microsoft Security Response Center (MSRC) at +[https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to +[secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your +message with our PGP key; please download it from the +[Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, +please follow up via email to ensure we received your original message. +Additional information can be found at +[microsoft.com/msrc](https://www.microsoft.com/msrc). -Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: +Please include the requested information listed below (as much as you can +provide) to help us better understand the nature and scope of the possible +issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, + etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. +If you are reporting for a bug bounty, more complete reports can contribute to a +higher bounty award. Please visit our +[Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more +details about our active programs. ## Preferred Languages @@ -36,6 +57,7 @@ We prefer all communications to be in English. ## Policy -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). +Microsoft follows the principle of +[Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). diff --git a/extension.bundle.ts b/extension.bundle.ts index 0cd4aff0d..aef525815 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -12,38 +12,66 @@ // Export activate/deactivate for main.js // The tests use instanceof against these and therefore we need to make sure we're using the same version of the bson module in the tests as in the bundle, // so export it from the bundle itself. -export { ObjectID, ObjectId } from 'bson'; +export { ObjectID, ObjectId } from "bson"; // Exports for tests // The tests are not packaged with the webpack bundle and therefore only have access to code exported from this file. // // The tests should import '../extension.bundle.ts'. At design-time they live in tests/ and so will pick up this file (extension.bundle.ts). // At runtime the tests live in dist/tests and will therefore pick up the main webpack bundle at dist/extension.bundle.js. -export { AzureAccountTreeItemBase, createAzureClient } from '@microsoft/vscode-azext-azureutils'; -export * from '@microsoft/vscode-azext-utils'; -export { emulatorPassword, isWindows } from './src/constants'; -export { ParsedDocDBConnectionString, parseDocDBConnectionString } from './src/docdb/docDBConnectionStrings'; -export { getCosmosClient } from './src/docdb/getCosmosClient'; -export * from './src/docdb/registerDocDBCommands'; -export { activateInternal, cosmosDBCopyConnectionString, createServer, deactivateInternal, deleteAccount } from './src/extension'; -export { ext } from './src/extensionVariables'; -export * from './src/graph/registerGraphCommands'; -export { connectToMongoClient, isCosmosEmulatorConnectionString } from './src/mongo/connectToMongoClient'; -export { MongoCommand } from './src/mongo/MongoCommand'; -export { addDatabaseToAccountConnectionString, encodeMongoConnectionString, getDatabaseNameFromConnectionString } from './src/mongo/mongoConnectionStrings'; -export { findCommandAtPosition, getAllCommandsFromText } from './src/mongo/MongoScrapbook'; -export { MongoShell } from './src/mongo/MongoShell'; -export * from './src/mongo/registerMongoCommands'; -export { IDatabaseInfo } from './src/mongo/tree/MongoAccountTreeItem'; -export { addDatabaseToConnectionString } from './src/postgres/postgresConnectionStrings'; -export { AttachedAccountsTreeItem, MONGO_CONNECTION_EXPECTED } from './src/tree/AttachedAccountsTreeItem'; -export { AzureAccountTreeItemWithAttached } from './src/tree/AzureAccountTreeItemWithAttached'; -export * from './src/utils/azureClients'; -export { improveError } from './src/utils/improveError'; -export { randomUtils } from './src/utils/randomUtils'; -export { getGlobalSetting, updateGlobalSetting } from './src/utils/settingUtils'; -export { rejectOnTimeout, valueOnTimeout } from './src/utils/timeout'; -export { getDocumentTreeItemLabel, IDisposable } from './src/utils/vscodeUtils'; -export { wrapError } from './src/utils/wrapError'; -export { isIpInRanges, getPublicIpv4 } from './src/utils/getIp' +export { + AzureAccountTreeItemBase, + createAzureClient, +} from "@microsoft/vscode-azext-azureutils"; +export * from "@microsoft/vscode-azext-utils"; +export { emulatorPassword, isWindows } from "./src/constants"; +export { + ParsedDocDBConnectionString, + parseDocDBConnectionString, +} from "./src/docdb/docDBConnectionStrings"; +export { getCosmosClient } from "./src/docdb/getCosmosClient"; +export * from "./src/docdb/registerDocDBCommands"; +export { + activateInternal, + cosmosDBCopyConnectionString, + createServer, + deactivateInternal, + deleteAccount, +} from "./src/extension"; +export { ext } from "./src/extensionVariables"; +export * from "./src/graph/registerGraphCommands"; +export { + connectToMongoClient, + isCosmosEmulatorConnectionString, +} from "./src/mongo/connectToMongoClient"; +export { MongoCommand } from "./src/mongo/MongoCommand"; +export { + addDatabaseToAccountConnectionString, + encodeMongoConnectionString, + getDatabaseNameFromConnectionString, +} from "./src/mongo/mongoConnectionStrings"; +export { + findCommandAtPosition, + getAllCommandsFromText, +} from "./src/mongo/MongoScrapbook"; +export { MongoShell } from "./src/mongo/MongoShell"; +export * from "./src/mongo/registerMongoCommands"; +export { IDatabaseInfo } from "./src/mongo/tree/MongoAccountTreeItem"; +export { addDatabaseToConnectionString } from "./src/postgres/postgresConnectionStrings"; +export { + AttachedAccountsTreeItem, + MONGO_CONNECTION_EXPECTED, +} from "./src/tree/AttachedAccountsTreeItem"; +export { AzureAccountTreeItemWithAttached } from "./src/tree/AzureAccountTreeItemWithAttached"; +export * from "./src/utils/azureClients"; +export { improveError } from "./src/utils/improveError"; +export { randomUtils } from "./src/utils/randomUtils"; +export { + getGlobalSetting, + updateGlobalSetting, +} from "./src/utils/settingUtils"; +export { rejectOnTimeout, valueOnTimeout } from "./src/utils/timeout"; +export { getDocumentTreeItemLabel, IDisposable } from "./src/utils/vscodeUtils"; +export { wrapError } from "./src/utils/wrapError"; +export { isIpInRanges, getPublicIpv4 } from "./src/utils/getIp"; // NOTE: The auto-fix action "source.organizeImports" does weird things with this file, but there doesn't seem to be a way to disable it on a per-file basis so we'll just let it happen diff --git a/gulpfile.ts b/gulpfile.ts index 3e69c1ffd..55888b8c4 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -3,29 +3,36 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { gulp_webpack } from '@microsoft/vscode-azext-dev'; -import * as fse from 'fs-extra'; -import * as gulp from 'gulp'; -import * as path from 'path'; +import { gulp_webpack } from "@microsoft/vscode-azext-dev"; +import * as fse from "fs-extra"; +import * as gulp from "gulp"; +import * as path from "path"; declare let exports: { [key: string]: unknown }; async function prepareForWebpack(): Promise { - const mainJsPath: string = path.join(__dirname, 'main.js'); - let contents: string = (await fse.readFile(mainJsPath)).toString(); - contents = contents - .replace('out/src/extension', 'dist/extension.bundle') - .replace(', true /* ignoreBundle */', ''); - await fse.writeFile(mainJsPath, contents); + const mainJsPath: string = path.join(__dirname, "main.js"); + let contents: string = (await fse.readFile(mainJsPath)).toString(); + contents = contents + .replace("out/src/extension", "dist/extension.bundle") + .replace(", true /* ignoreBundle */", ""); + await fse.writeFile(mainJsPath, contents); } async function cleanReadme(): Promise { - const readmePath: string = path.join(__dirname, 'README.md'); - let data: string = (await fse.readFile(readmePath)).toString(); - data = data.replace(/.*?/gis, ''); - await fse.writeFile(readmePath, data); + const readmePath: string = path.join(__dirname, "README.md"); + let data: string = (await fse.readFile(readmePath)).toString(); + data = data.replace( + /.*?/gis, + "" + ); + await fse.writeFile(readmePath, data); } -exports['webpack-dev'] = gulp.series(prepareForWebpack, () => gulp_webpack('development')); -exports['webpack-prod'] = gulp.series(prepareForWebpack, () => gulp_webpack('production')); +exports["webpack-dev"] = gulp.series(prepareForWebpack, () => + gulp_webpack("development") +); +exports["webpack-prod"] = gulp.series(prepareForWebpack, () => + gulp_webpack("production") +); exports.cleanReadme = cleanReadme; diff --git a/main.js b/main.js index 01717236a..3fa51d0fb 100644 --- a/main.js +++ b/main.js @@ -10,20 +10,24 @@ // This is in a separate file so we can properly measure extension.bundle.js load time. let perfStats = { - loadStartTime: Date.now(), - loadEndTime: undefined + loadStartTime: Date.now(), + loadEndTime: undefined, }; Object.defineProperty(exports, "__esModule", { value: true }); -const extension = require('./out/src/extension'); +const extension = require("./out/src/extension"); async function activate(ctx) { - return await extension.activateInternal(ctx, perfStats, true /* ignoreBundle */); + return await extension.activateInternal( + ctx, + perfStats, + true /* ignoreBundle */ + ); } async function deactivate(ctx) { - return await extension.deactivateInternal(ctx, perfStats); + return await extension.deactivateInternal(ctx, perfStats); } // Export as entrypoints for vscode diff --git a/package.json b/package.json index bb94c33c7..dfd4d922c 100644 --- a/package.json +++ b/package.json @@ -1,1112 +1,1112 @@ { - "name": "vscode-cosmosdb", - "version": "0.0.1", - "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", - "publisher": "playform", - "displayName": "Azure Databases", - "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", - "galleryBanner": { - "color": "#3c3c3c", - "theme": "dark" - }, - "icon": "resources/databases.png", - "preview": true, - "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", - "bugs": { - "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" - }, - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" - }, - "main": "./main", - "activationEvents": [ - "onCommand:azureDatabases.createServer", - "onCommand:azureDatabases.detachDatabaseAccount", - "onCommand:azureDatabases.loadMore", - "onCommand:azureDatabases.refresh", - "onCommand:azureDatabases.reportIssue", - "onCommand:azureDatabases.update", - "onCommand:cosmosDB.attachDatabaseAccount", - "onCommand:cosmosDB.attachEmulator", - "onCommand:cosmosDB.connectMongoDB", - "onCommand:cosmosDB.copyConnectionString", - "onCommand:cosmosDB.createDocDBCollection", - "onCommand:cosmosDB.createDocDBDatabase", - "onCommand:cosmosDB.createDocDBDocument", - "onCommand:cosmosDB.createDocDBStoredProcedure", - "onCommand:cosmosDB.createGraph", - "onCommand:cosmosDB.createGraphDatabase", - "onCommand:cosmosDB.createMongoCollection", - "onCommand:cosmosDB.createMongoDatabase", - "onCommand:cosmosDB.createMongoDocument", - "onCommand:cosmosDB.deleteAccount", - "onCommand:cosmosDB.deleteDocDBCollection", - "onCommand:cosmosDB.deleteDocDBDatabase", - "onCommand:cosmosDB.deleteDocDBDocument", - "onCommand:cosmosDB.deleteGraph", - "onCommand:cosmosDB.deleteGraphDatabase", - "onCommand:cosmosDB.deleteMongoCollection", - "onCommand:cosmosDB.deleteMongoDB", - "onCommand:cosmosDB.deleteMongoDocument", - "onCommand:cosmosDB.executeAllMongoCommands", - "onCommand:cosmosDB.executeMongoCommand", - "onCommand:cosmosDB.importDocument", - "onCommand:cosmosDB.launchMongoShell", - "onCommand:cosmosDB.newMongoScrapbook", - "onCommand:cosmosDB.openCollection", - "onCommand:cosmosDB.openDocument", - "onCommand:cosmosDB.openGraphExplorer", - "onCommand:cosmosDB.openStoredProcedure", - "onCommand:postgreSQL.configureFirewall", - "onCommand:postgreSQL.connectDatabase", - "onCommand:postgreSQL.createDatabase", - "onCommand:postgreSQL.createFunctionQuery", - "onCommand:postgreSQL.createStoredProcedureQuery", - "onCommand:postgreSQL.deleteDatabase", - "onCommand:postgreSQL.deleteFunction", - "onCommand:postgreSQL.deleteServer", - "onCommand:postgreSQL.deleteStoredProcedure", - "onCommand:postgreSQL.deleteTable", - "onCommand:postgreSQL.enterCredentials", - "onCommand:postgreSQL.executeQuery", - "onCommand:postgreSQL.openFunction", - "onCommand:postgreSQL.openStoredProcedure", - "onFileSystem:azureDatabases", - "onLanguage:mongo", - "onView:azureWorkspace" - ], - "contributes": { - "x-azResources": { - "azure": { - "branches": [ - { - "type": "AzureCosmosDb" - }, - { - "type": "PostgresqlServersStandard" - }, - { - "type": "PostgresqlServersFlexible" - } - ] - }, - "workspace": { - "branches": [ - { - "type": "ms-azuretools.vscode-cosmosdb" - } - ], - "resources": true - }, - "commands": [ - { - "command": "azureDatabases.createServer", - "title": "Create Database Server...", - "type": "microsoft.documentdb/databaseaccounts", - "detail": "SQL or NoSQL databases for your web apps." - } - ], - "activation": { - "onResolve": [ - "microsoft.documentdb/databaseaccounts", - "microsoft.dbforpostgresql/servers", - "microsoft.dbforpostgresql/flexibleservers" - ] - } - }, - "languages": [ - { - "id": "mongo", - "aliases": [ - "Mongo Scrapbook", - "mongo" - ], - "extensions": [ - ".mongo" - ], - "firstLine": "^#!/.*\\bmongo*\\b", - "configuration": "./grammar/configuration.json" - }, - { - "id": "postgres", - "aliases": [ - "PostgreSQL" - ], - "extensions": [ - ".psql" - ] - } - ], - "grammars": [ - { - "language": "mongo", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } - ], - "commands": [ - { - "category": "Azure Databases", - "command": "azureDatabases.createServer", - "title": "Create Server...", - "icon": "$(add)" - }, - { - "category": "Cosmos DB", - "command": "azureDatabases.detachDatabaseAccount", - "title": "Detach" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.loadMore", - "title": "Load More" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.refresh", - "title": "Refresh", - "icon": "$(refresh)" - }, - { - "category": "Azure Databases", - "command": "azureDatabases.reportIssue", - "title": "Report Issue..." - }, - { - "category": "Azure Databases", - "command": "azureDatabases.update", - "title": "Update to Cloud", - "icon": "$(cloud-upload)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachDatabaseAccount", - "title": "Attach Database Account...", - "icon": "$(plug)" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.attachEmulator", - "title": "Attach Emulator..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.connectMongoDB", - "title": "Connect to Database..." - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBCollection", - "title": "Create Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDatabase", - "title": "Create Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBDocument", - "title": "Create Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.createDocDBStoredProcedure", - "title": "Create Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraph", - "title": "Create Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.createGraphDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoCollection", - "title": "Create Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDatabase", - "title": "Create Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.createMongoDocument", - "title": "Create Document" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.deleteAccount", - "title": "Delete Account..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBCollection", - "title": "Delete Collection..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDatabase", - "title": "Delete Database..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBDocument", - "title": "Delete Document..." - }, - { - "category": "Core (SQL)", - "command": "cosmosDB.deleteDocDBStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraph", - "title": "Delete Graph..." - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.deleteGraphDatabase", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoCollection", - "title": "Delete Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDB", - "title": "Delete Database..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.deleteMongoDocument", - "title": "Delete Document..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeAllMongoCommands", - "title": "Execute All MongoDB Commands" - }, - { - "category": "MongoDB", - "command": "cosmosDB.executeMongoCommand", - "title": "Execute MongoDB Command" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.importDocument", - "title": "Import Document into a Collection..." - }, - { - "category": "MongoDB", - "command": "cosmosDB.launchMongoShell", - "title": "Launch Shell" - }, - { - "category": "MongoDB", - "command": "cosmosDB.newMongoScrapbook", - "title": "New Mongo Scrapbook", - "icon": "$(new-file)" - }, - { - "category": "MongoDB", - "command": "cosmosDB.openCollection", - "title": "Open Collection" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openDocument", - "title": "Open Document" - }, - { - "category": "Graph (Gremlin)", - "command": "cosmosDB.openGraphExplorer", - "title": "Open Graph Explorer" - }, - { - "category": "Cosmos DB", - "command": "cosmosDB.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.configureFirewall", - "title": "Configure Firewall" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.connectDatabase", - "title": "Connect to Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.copyConnectionString", - "title": "Copy Connection String" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createDatabase", - "title": "Create Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createFunctionQuery", - "title": "Create Function Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.createStoredProcedureQuery", - "title": "Create Stored Procedure Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteDatabase", - "title": "Delete Database..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteFunction", - "title": "Delete Function..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteServer", - "title": "Delete Server..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteStoredProcedure", - "title": "Delete Stored Procedure..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.deleteTable", - "title": "Delete Table..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.enterCredentials", - "title": "Enter Server Credentials" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.executeQuery", - "title": "Execute Query..." - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openFunction", - "title": "Open Function" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.openStoredProcedure", - "title": "Open Stored Procedure" - }, - { - "category": "PostgreSQL", - "command": "postgreSQL.showPasswordlessWiki", - "title": "Learn more about authenticating with Azure Active Directory", - "icon": "$(warning)" - } - ], - "submenus": [ - { - "id": "azureDatabases.submenus.workspaceActions", - "label": "Azure Databases", - "icon": "resources/databases.png" - } - ], - "menus": { - "azureDatabases.submenus.workspaceActions": [ - { - "command": "cosmosDB.attachDatabaseAccount", - "group": "1_attach@1" - } - ], - "view/title": [ - { - "submenu": "azureDatabases.submenus.workspaceActions", - "when": "view == azureWorkspace", - "group": "navigation@6" - } - ], - "editor/context": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "resourceLangId==mongo" - }, - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId==json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId==postgres" - } - ], - "editor/title": [ - { - "command": "azureDatabases.update", - "when": "resourceFilename==cosmos-result.json", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", - "group": "navigation" - }, - { - "command": "azureDatabases.update", - "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "azureDatabases.createServer", - "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", - "group": "1@1" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteAccount", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteServer", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@2" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@1" - }, - { - "command": "cosmosDB.createMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createDocDBDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraphDatabase", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@1" - }, - { - "command": "cosmosDB.createGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@1" - }, - { - "command": "postgreSQL.showPasswordlessWiki", - "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", - "group": "inline" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createDatabase", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@1" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "1@2" - }, - { - "command": "azureDatabases.detachDatabaseAccount", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "1@2" - }, - { - "command": "cosmosDB.connectMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "2@1" - }, - { - "command": "cosmosDB.deleteMongoDB", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteMongoCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@4" - }, - { - "command": "cosmosDB.deleteMongoDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteDocDBDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraphDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteTable", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteFunction", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", - "group": "1@2" - }, - { - "command": "postgreSQL.deleteStoredProcedure", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", - "group": "1@2" - }, - { - "command": "cosmosDB.deleteGraph", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", - "group": "1@2" - }, - { - "command": "cosmosDB.attachDatabaseAccount", - "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "1@1" - }, - { - "command": "cosmosDB.attachEmulator", - "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", - "group": "1@2" - }, - { - "command": "cosmosDB.openCollection", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@2" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "2@1" - }, - { - "command": "cosmosDB.copyConnectionString", - "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", - "group": "2@1" - }, - { - "command": "postgreSQL.copyConnectionString", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", - "group": "2@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", - "group": "1@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", - "group": "3@2" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem == postgresServerAttached", - "group": "2@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", - "group": "3@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "4@1" - }, - { - "command": "azureDatabases.refresh", - "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", - "group": "2@1" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", - "group": "1@3" - }, - { - "command": "cosmosDB.importDocument", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", - "group": "1@1" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", - "group": "1@1" - }, - { - "command": "postgreSQL.createFunctionQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", - "group": "1@1" - }, - { - "command": "postgreSQL.createStoredProcedureQuery", - "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", - "group": "1@1" - } - ], - "explorer/context": [ - { - "command": "cosmosDB.importDocument", - "when": "resourceLangId == json" - }, - { - "command": "postgreSQL.connectDatabase", - "when": "resourceLangId == postgres" - } - ], - "commandPalette": [ - { - "command": "azureDatabases.loadMore", - "when": "never" - }, - { - "command": "azureDatabases.refresh", - "when": "never" - }, - { - "command": "azureDatabases.update", - "when": "never" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "when": "editorLangId == 'mongo'" - }, - { - "command": "cosmosDB.executeMongoCommand", - "when": "editorLangId == 'mongo'" - }, - { - "command": "postgreSQL.executeQuery", - "when": "editorLangId == 'postgres'" - } - ] - }, - "keybindings": [ - { - "command": "cosmosDB.executeMongoCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'mongo' && editorTextFocus" - }, - { - "command": "cosmosDB.executeAllMongoCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'mongo' && editorTextFocus" - } - ], - "configuration": { - "title": "Azure Databases", - "properties": { - "mongo.shell.path": { - "type": [ - "string", - "null" - ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", - "default": null - }, - "mongo.shell.args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass when starting the Mongo shell.", - "default": [ - "--quiet" - ] - }, - "mongo.shell.timeout": { - "type": "number", - "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", - "default": 30 - }, - "azureDatabases.showExplorer": { - "type": "boolean", - "default": true, - "description": "Show or hide the Azure Databases Explorer" - }, - "cosmosDB.documentLabelFields": { - "type": "array", - "default": [ - "name", - "Name", - "NAME", - "ID", - "UUID", - "Id", - "id", - "_id", - "uuid" - ], - "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" - }, - "cosmosDB.enableEndpointDiscovery": { - "type": "boolean", - "default": true, - "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." - }, - "cosmosDB.showSavePrompt": { - "type": "boolean", - "default": true, - "description": "Show warning dialog when uploading a document to the cloud." - }, - "azureDatabases.batchSize": { - "type": "number", - "description": "The batch size to be used when querying Azure Database resources.", - "default": 50 - }, - "azureDatabases.enableOutputTimestamps": { - "type": "boolean", - "default": true, - "description": "Prepends each line displayed in the output channel with a timestamp." - }, - "cosmosDB.emulator.mongoPort": { - "type": "integer", - "default": 10255, - "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" - }, - "cosmosDB.emulator.port": { - "type": "integer", - "default": 8081, - "description": "Port to use when connecting to a CosmosDB Emulator instance" - } - } - } - }, - "scripts": { - "vscode:prepublish": "npm run webpack-prod", - "build": "tsc", - "cleanReadme": "gulp cleanReadme", - "clean": "git clean -dfx", - "compile": "tsc -watch", - "package": "vsce package --githubBranch main", - "package-local": "vsce package", - "lint": "eslint --ext .ts .", - "lint-fix": "eslint --ext .ts . --fix", - "pretest": "npm run webpack-prod", - "test": "node ./out/test/runTest.js", - "unittest": "mocha ./out/test/unit/**/*.js", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", - "webpack": "npm run build && gulp webpack-dev", - "webpack-prod": "npm run build && gulp webpack-prod", - "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats", - "all": "npm i && npm run lint && npm test", - "prepare": "husky install", - "prepublishOnly": "TypeScriptESBuild 'Source/**/*.ts'" - }, - "devDependencies": { - "@azure/arm-resources": "5.2.0", - "@microsoft/eslint-config-azuretools": "0.2.2", - "@microsoft/vscode-azext-dev": "2.0.2", - "@types/copy-webpack-plugin": "8.0.1", - "@types/documentdb": "1.10.13", - "@types/fs-extra": "11.0.4", - "@types/gulp": "4.0.17", - "@types/mocha": "10.0.6", - "@types/mongodb": "4.0.6", - "@types/node": "20.10.0", - "@types/pg": "8.10.9", - "@types/vscode": "1.84.2", - "@typescript-eslint/eslint-plugin": "6.12.0", - "@vscode/test-electron": "2.3.8", - "antlr4ts-cli": "0.5.0-alpha.4", - "copy-webpack-plugin": "11.0.0", - "eslint": "8.54.0", - "eslint-plugin-import": "2.29.0", - "glob": "10.3.10", - "gulp": "4.0.2", - "husky": "8.0.3", - "mocha": "10.2.0", - "mocha-junit-reporter": "2.2.1", - "mocha-multi-reporters": "1.5.1", - "ts-node": "10.9.1", - "typescript": "5.3.2", - "vsce": "1.87.0", - "webpack": "5.89.0", - "webpack-cli": "5.1.4", - "webpack-log": "3.0.2", - "typescript-esbuild": "0.3.1" - }, - "dependencies": { - "@azure/arm-cosmosdb": "15.5.0", - "@azure/arm-postgresql": "6.1.0", - "@azure/arm-postgresql-flexible": "7.1.0", - "@azure/cosmos": "4.0.0", - "@microsoft/vscode-azext-azureutils": "2.0.2", - "@microsoft/vscode-azext-utils": "2.1.3", - "antlr4ts": "0.5.0-alpha.4", - "bson": "6.2.0", - "fs-extra": "11.1.1", - "mongodb": "6.3.0", - "mongodb-extended-json": "1.10.0", - "open": "9.1.0", - "pg": "8.11.3", - "pg-connection-string": "2.6.2", - "pg-structure": "7.15.0", - "semver": "7.5.4", - "underscore": "1.13.6", - "vscode-json-languageservice": "5.3.7", - "vscode-languageclient": "9.0.1", - "vscode-languageserver": "9.0.1", - "vscode-languageserver-textdocument": "1.0.11", - "vscode-nls": "5.2.0", - "vscode-uri": "3.0.8" - }, - "extensionDependencies": [ - "ms-azuretools.vscode-azureresourcegroups" - ], - "type": "module", - "private": "false", - "publishConfig": { - "access": "public" - }, - "author": { - "name": "Nikola Hristov", - "email": "nikola@nikolahristov.tech", - "url": "https://nikolahristov.tech" - } + "name": "vscode-cosmosdb", + "displayName": "Azure Databases", + "version": "0.0.1", + "private": "false", + "description": "Create, browse, and update globally distributed, multi-model databases in Azure.", + "homepage": "https://github.com/CodeEditorLand/CodeEditorLand#readme", + "bugs": { + "url": "https://github.com/CodeEditorLand/CodeEditorLand/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/CodeEditorLand/CodeEditorLand.git" + }, + "license": "MIT", + "author": { + "name": "Nikola Hristov", + "email": "nikola@nikolahristov.tech", + "url": "https://nikolahristov.tech" + }, + "publisher": "playform", + "type": "module", + "main": "./main", + "scripts": { + "all": "npm i && npm run lint && npm test", + "build": "tsc", + "clean": "git clean -dfx", + "cleanReadme": "gulp cleanReadme", + "compile": "tsc -watch", + "lint": "eslint --ext .ts .", + "lint-fix": "eslint --ext .ts . --fix", + "package": "vsce package --githubBranch main", + "package-local": "vsce package", + "prepare": "husky install", + "prepublishOnly": "TypeScriptESBuild 'Source/**/*.ts'", + "pretest": "npm run webpack-prod", + "test": "node ./out/test/runTest.js", + "unittest": "mocha ./out/test/unit/**/*.js", + "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o ./src/mongo/grammar", + "vscode:prepublish": "npm run webpack-prod", + "webpack": "npm run build && gulp webpack-dev", + "webpack-prod": "npm run build && gulp webpack-prod", + "webpack-profile": "webpack --profile --json --mode production > webpack-stats.json && echo Use http://webpack.github.io/analyse to analyze the stats" + }, + "contributes": { + "commands": [ + { + "category": "Azure Databases", + "command": "azureDatabases.createServer", + "title": "Create Server...", + "icon": "$(add)" + }, + { + "category": "Cosmos DB", + "command": "azureDatabases.detachDatabaseAccount", + "title": "Detach" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.loadMore", + "title": "Load More" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, + { + "category": "Azure Databases", + "command": "azureDatabases.reportIssue", + "title": "Report Issue..." + }, + { + "category": "Azure Databases", + "command": "azureDatabases.update", + "title": "Update to Cloud", + "icon": "$(cloud-upload)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachDatabaseAccount", + "title": "Attach Database Account...", + "icon": "$(plug)" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.attachEmulator", + "title": "Attach Emulator..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.connectMongoDB", + "title": "Connect to Database..." + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBCollection", + "title": "Create Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDatabase", + "title": "Create Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBDocument", + "title": "Create Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.createDocDBStoredProcedure", + "title": "Create Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraph", + "title": "Create Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.createGraphDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoCollection", + "title": "Create Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDatabase", + "title": "Create Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.createMongoDocument", + "title": "Create Document" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.deleteAccount", + "title": "Delete Account..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBCollection", + "title": "Delete Collection..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDatabase", + "title": "Delete Database..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBDocument", + "title": "Delete Document..." + }, + { + "category": "Core (SQL)", + "command": "cosmosDB.deleteDocDBStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraph", + "title": "Delete Graph..." + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.deleteGraphDatabase", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoCollection", + "title": "Delete Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDB", + "title": "Delete Database..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.deleteMongoDocument", + "title": "Delete Document..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeAllMongoCommands", + "title": "Execute All MongoDB Commands" + }, + { + "category": "MongoDB", + "command": "cosmosDB.executeMongoCommand", + "title": "Execute MongoDB Command" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.importDocument", + "title": "Import Document into a Collection..." + }, + { + "category": "MongoDB", + "command": "cosmosDB.launchMongoShell", + "title": "Launch Shell" + }, + { + "category": "MongoDB", + "command": "cosmosDB.newMongoScrapbook", + "title": "New Mongo Scrapbook", + "icon": "$(new-file)" + }, + { + "category": "MongoDB", + "command": "cosmosDB.openCollection", + "title": "Open Collection" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openDocument", + "title": "Open Document" + }, + { + "category": "Graph (Gremlin)", + "command": "cosmosDB.openGraphExplorer", + "title": "Open Graph Explorer" + }, + { + "category": "Cosmos DB", + "command": "cosmosDB.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.configureFirewall", + "title": "Configure Firewall" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.connectDatabase", + "title": "Connect to Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.copyConnectionString", + "title": "Copy Connection String" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createDatabase", + "title": "Create Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createFunctionQuery", + "title": "Create Function Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.createStoredProcedureQuery", + "title": "Create Stored Procedure Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteDatabase", + "title": "Delete Database..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteFunction", + "title": "Delete Function..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteServer", + "title": "Delete Server..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteStoredProcedure", + "title": "Delete Stored Procedure..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.deleteTable", + "title": "Delete Table..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.enterCredentials", + "title": "Enter Server Credentials" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.executeQuery", + "title": "Execute Query..." + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openFunction", + "title": "Open Function" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.openStoredProcedure", + "title": "Open Stored Procedure" + }, + { + "category": "PostgreSQL", + "command": "postgreSQL.showPasswordlessWiki", + "title": "Learn more about authenticating with Azure Active Directory", + "icon": "$(warning)" + } + ], + "configuration": { + "title": "Azure Databases", + "properties": { + "mongo.shell.path": { + "type": [ + "string", + "null" + ], + "description": "Full path to folder and executable to start the Mongo shell, needed by some Mongo scrapbook commands. The default is to search in the system path for 'mongo'.", + "default": null + }, + "mongo.shell.args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass when starting the Mongo shell.", + "default": [ + "--quiet" + ] + }, + "mongo.shell.timeout": { + "type": "number", + "description": "The duration allowed (in seconds) for the Mongo shell to execute a command. Default value is 30 seconds.", + "default": 30 + }, + "azureDatabases.showExplorer": { + "type": "boolean", + "default": true, + "description": "Show or hide the Azure Databases Explorer" + }, + "cosmosDB.documentLabelFields": { + "type": "array", + "default": [ + "name", + "Name", + "NAME", + "ID", + "UUID", + "Id", + "id", + "_id", + "uuid" + ], + "description": "The field values to display as labels in the treeview for Cosmos DB and MongoDB documents, in priority order" + }, + "cosmosDB.enableEndpointDiscovery": { + "type": "boolean", + "default": true, + "description": "Flag to enable/disable automatic redirecting of requests based on read/write operations." + }, + "cosmosDB.showSavePrompt": { + "type": "boolean", + "default": true, + "description": "Show warning dialog when uploading a document to the cloud." + }, + "azureDatabases.batchSize": { + "type": "number", + "description": "The batch size to be used when querying Azure Database resources.", + "default": 50 + }, + "azureDatabases.enableOutputTimestamps": { + "type": "boolean", + "default": true, + "description": "Prepends each line displayed in the output channel with a timestamp." + }, + "cosmosDB.emulator.mongoPort": { + "type": "integer", + "default": 10255, + "description": "Port to use when connecting to a CosmosDB Mongo Emulator instance" + }, + "cosmosDB.emulator.port": { + "type": "integer", + "default": 8081, + "description": "Port to use when connecting to a CosmosDB Emulator instance" + } + } + }, + "grammars": [ + { + "language": "mongo", + "scopeName": "source.mongo.js", + "path": "./grammar/JavaScript.tmLanguage.json" + }, + { + "scopeName": "source.mongo.js.regexp", + "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" + } + ], + "keybindings": [ + { + "command": "cosmosDB.executeMongoCommand", + "key": "ctrl+shift+'", + "mac": "cmd+shift+'", + "when": "editorLangId == 'mongo' && editorTextFocus" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "key": "ctrl+shift+;", + "mac": "cmd+shift+;", + "when": "editorLangId == 'mongo' && editorTextFocus" + } + ], + "languages": [ + { + "id": "mongo", + "aliases": [ + "Mongo Scrapbook", + "mongo" + ], + "extensions": [ + ".mongo" + ], + "firstLine": "^#!/.*\\bmongo*\\b", + "configuration": "./grammar/configuration.json" + }, + { + "id": "postgres", + "aliases": [ + "PostgreSQL" + ], + "extensions": [ + ".psql" + ] + } + ], + "menus": { + "azureDatabases.submenus.workspaceActions": [ + { + "command": "cosmosDB.attachDatabaseAccount", + "group": "1_attach@1" + } + ], + "view/title": [ + { + "submenu": "azureDatabases.submenus.workspaceActions", + "when": "view == azureWorkspace", + "group": "navigation@6" + } + ], + "editor/context": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)/" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)/" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "resourceLangId==mongo" + }, + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId==json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId==postgres" + } + ], + "editor/title": [ + { + "command": "azureDatabases.update", + "when": "resourceFilename==cosmos-result.json", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-document[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-collection[.]json)(?![a-z])/i", + "group": "navigation" + }, + { + "command": "azureDatabases.update", + "when": "resourceFilename=~/(.*cosmos-stored-procedure[.]js)(?![a-z])/i", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "azureDatabases.createServer", + "when": "view == azureResourceGroups && viewItem =~ /(AzureCosmosDb|PostgreSqlServers(Standard|Flexible))/i && viewItem =~ /azureResourceTypeGroup/i", + "group": "1@1" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteAccount", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteServer", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@2" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@1" + }, + { + "command": "cosmosDB.createMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createDocDBDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraphDatabase", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@1" + }, + { + "command": "cosmosDB.createGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@1" + }, + { + "command": "postgreSQL.showPasswordlessWiki", + "when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i", + "group": "inline" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createDatabase", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@1" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "1@2" + }, + { + "command": "azureDatabases.detachDatabaseAccount", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "1@2" + }, + { + "command": "cosmosDB.connectMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "2@1" + }, + { + "command": "cosmosDB.deleteMongoDB", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteMongoCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@4" + }, + { + "command": "cosmosDB.deleteMongoDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocument", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteDocDBDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraphDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteTable", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTable", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteFunction", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunction", + "group": "1@2" + }, + { + "command": "postgreSQL.deleteStoredProcedure", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedure", + "group": "1@2" + }, + { + "command": "cosmosDB.deleteGraph", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraph", + "group": "1@2" + }, + { + "command": "cosmosDB.attachDatabaseAccount", + "when": "view == azureWorkspace && viewItem =~ /cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "1@1" + }, + { + "command": "cosmosDB.attachEmulator", + "when": "view == azureWorkspace && viewItem == cosmosDBAttachedAccountsWithEmulator", + "group": "1@2" + }, + { + "command": "cosmosDB.openCollection", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@2" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBMongoServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /cosmosDBTableAccount(?![a-z])/i", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "2@1" + }, + { + "command": "cosmosDB.copyConnectionString", + "when": "view == azureWorkspace && viewItem == cosmosDBTableAccountAttached", + "group": "2@1" + }, + { + "command": "postgreSQL.copyConnectionString", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBMongoServerAttached", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentDatabase", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentsGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBStoredProceduresGroup", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBDocumentServer(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /postgresServer(?![a-z])/i", + "group": "2@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresTables", + "group": "1@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBDocumentServerAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azureWorkspace/ && viewItem =~ /cosmosDBGraphAccount(?![a-z])/i", + "group": "3@2" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == cosmosDBGraphAccountAttached", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem == postgresServerAttached", + "group": "2@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == mongoDb", + "group": "3@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "4@1" + }, + { + "command": "azureDatabases.refresh", + "when": "view == azureWorkspace && viewItem =~ /^cosmosDBAttachedAccounts(?![a-z])/gi", + "group": "2@1" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == MongoCollection", + "group": "1@3" + }, + { + "command": "cosmosDB.importDocument", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBDocumentCollection", + "group": "1@1" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i", + "group": "1@1" + }, + { + "command": "postgreSQL.createFunctionQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresFunctions", + "group": "1@1" + }, + { + "command": "postgreSQL.createStoredProcedureQuery", + "when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == postgresStoredProcedures", + "group": "1@1" + } + ], + "explorer/context": [ + { + "command": "cosmosDB.importDocument", + "when": "resourceLangId == json" + }, + { + "command": "postgreSQL.connectDatabase", + "when": "resourceLangId == postgres" + } + ], + "commandPalette": [ + { + "command": "azureDatabases.loadMore", + "when": "never" + }, + { + "command": "azureDatabases.refresh", + "when": "never" + }, + { + "command": "azureDatabases.update", + "when": "never" + }, + { + "command": "cosmosDB.executeAllMongoCommands", + "when": "editorLangId == 'mongo'" + }, + { + "command": "cosmosDB.executeMongoCommand", + "when": "editorLangId == 'mongo'" + }, + { + "command": "postgreSQL.executeQuery", + "when": "editorLangId == 'postgres'" + } + ] + }, + "submenus": [ + { + "id": "azureDatabases.submenus.workspaceActions", + "label": "Azure Databases", + "icon": "resources/databases.png" + } + ], + "x-azResources": { + "azure": { + "branches": [ + { + "type": "AzureCosmosDb" + }, + { + "type": "PostgresqlServersStandard" + }, + { + "type": "PostgresqlServersFlexible" + } + ] + }, + "workspace": { + "branches": [ + { + "type": "ms-azuretools.vscode-cosmosdb" + } + ], + "resources": true + }, + "commands": [ + { + "command": "azureDatabases.createServer", + "title": "Create Database Server...", + "type": "microsoft.documentdb/databaseaccounts", + "detail": "SQL or NoSQL databases for your web apps." + } + ], + "activation": { + "onResolve": [ + "microsoft.documentdb/databaseaccounts", + "microsoft.dbforpostgresql/servers", + "microsoft.dbforpostgresql/flexibleservers" + ] + } + } + }, + "activationEvents": [ + "onCommand:azureDatabases.createServer", + "onCommand:azureDatabases.detachDatabaseAccount", + "onCommand:azureDatabases.loadMore", + "onCommand:azureDatabases.refresh", + "onCommand:azureDatabases.reportIssue", + "onCommand:azureDatabases.update", + "onCommand:cosmosDB.attachDatabaseAccount", + "onCommand:cosmosDB.attachEmulator", + "onCommand:cosmosDB.connectMongoDB", + "onCommand:cosmosDB.copyConnectionString", + "onCommand:cosmosDB.createDocDBCollection", + "onCommand:cosmosDB.createDocDBDatabase", + "onCommand:cosmosDB.createDocDBDocument", + "onCommand:cosmosDB.createDocDBStoredProcedure", + "onCommand:cosmosDB.createGraph", + "onCommand:cosmosDB.createGraphDatabase", + "onCommand:cosmosDB.createMongoCollection", + "onCommand:cosmosDB.createMongoDatabase", + "onCommand:cosmosDB.createMongoDocument", + "onCommand:cosmosDB.deleteAccount", + "onCommand:cosmosDB.deleteDocDBCollection", + "onCommand:cosmosDB.deleteDocDBDatabase", + "onCommand:cosmosDB.deleteDocDBDocument", + "onCommand:cosmosDB.deleteGraph", + "onCommand:cosmosDB.deleteGraphDatabase", + "onCommand:cosmosDB.deleteMongoCollection", + "onCommand:cosmosDB.deleteMongoDB", + "onCommand:cosmosDB.deleteMongoDocument", + "onCommand:cosmosDB.executeAllMongoCommands", + "onCommand:cosmosDB.executeMongoCommand", + "onCommand:cosmosDB.importDocument", + "onCommand:cosmosDB.launchMongoShell", + "onCommand:cosmosDB.newMongoScrapbook", + "onCommand:cosmosDB.openCollection", + "onCommand:cosmosDB.openDocument", + "onCommand:cosmosDB.openGraphExplorer", + "onCommand:cosmosDB.openStoredProcedure", + "onCommand:postgreSQL.configureFirewall", + "onCommand:postgreSQL.connectDatabase", + "onCommand:postgreSQL.createDatabase", + "onCommand:postgreSQL.createFunctionQuery", + "onCommand:postgreSQL.createStoredProcedureQuery", + "onCommand:postgreSQL.deleteDatabase", + "onCommand:postgreSQL.deleteFunction", + "onCommand:postgreSQL.deleteServer", + "onCommand:postgreSQL.deleteStoredProcedure", + "onCommand:postgreSQL.deleteTable", + "onCommand:postgreSQL.enterCredentials", + "onCommand:postgreSQL.executeQuery", + "onCommand:postgreSQL.openFunction", + "onCommand:postgreSQL.openStoredProcedure", + "onFileSystem:azureDatabases", + "onLanguage:mongo", + "onView:azureWorkspace" + ], + "dependencies": { + "@azure/arm-cosmosdb": "15.5.0", + "@azure/arm-postgresql": "6.1.0", + "@azure/arm-postgresql-flexible": "7.1.0", + "@azure/cosmos": "4.0.0", + "@microsoft/vscode-azext-azureutils": "2.0.2", + "@microsoft/vscode-azext-utils": "2.1.3", + "antlr4ts": "0.5.0-alpha.4", + "bson": "6.2.0", + "fs-extra": "11.1.1", + "mongodb": "6.3.0", + "mongodb-extended-json": "1.10.0", + "open": "9.1.0", + "pg": "8.11.3", + "pg-connection-string": "2.6.2", + "pg-structure": "7.15.0", + "semver": "7.5.4", + "underscore": "1.13.6", + "vscode-json-languageservice": "5.3.7", + "vscode-languageclient": "9.0.1", + "vscode-languageserver": "9.0.1", + "vscode-languageserver-textdocument": "1.0.11", + "vscode-nls": "5.2.0", + "vscode-uri": "3.0.8" + }, + "devDependencies": { + "@azure/arm-resources": "5.2.0", + "@microsoft/eslint-config-azuretools": "0.2.2", + "@microsoft/vscode-azext-dev": "2.0.2", + "@types/copy-webpack-plugin": "8.0.1", + "@types/documentdb": "1.10.13", + "@types/fs-extra": "11.0.4", + "@types/gulp": "4.0.17", + "@types/mocha": "10.0.6", + "@types/mongodb": "4.0.6", + "@types/node": "20.10.0", + "@types/pg": "8.10.9", + "@types/vscode": "1.84.2", + "@typescript-eslint/eslint-plugin": "6.12.0", + "@vscode/test-electron": "2.3.8", + "antlr4ts-cli": "0.5.0-alpha.4", + "copy-webpack-plugin": "11.0.0", + "eslint": "8.54.0", + "eslint-plugin-import": "2.29.0", + "glob": "10.3.10", + "gulp": "4.0.2", + "husky": "8.0.3", + "mocha": "10.2.0", + "mocha-junit-reporter": "2.2.1", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "5.3.2", + "typescript-esbuild": "0.3.1", + "vsce": "1.87.0", + "webpack": "5.89.0", + "webpack-cli": "5.1.4", + "webpack-log": "3.0.2" + }, + "extensionDependencies": [ + "ms-azuretools.vscode-azureresourcegroups" + ], + "publishConfig": { + "access": "public" + }, + "icon": "resources/databases.png", + "galleryBanner": { + "color": "#3c3c3c", + "theme": "dark" + }, + "preview": true, + "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255" } diff --git a/tsconfig.json b/tsconfig.json index 70851034c..2a36e70e3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,33 +1,23 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6", - "dom" - ], - "sourceMap": true, - "noImplicitThis": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "strictNullChecks": true, - "skipLibCheck": true, - "noUnusedParameters": true, - "rootDir": ".", - "experimentalDecorators": true, - "baseUrl": "./", - "alwaysStrict": true, - "paths": { - "*": [ - "node_modules/@types/*", - "*" - ] - } - }, - "exclude": [ - "node_modules", - ".vscode-test", - "gulpfile.ts" - ] + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": ["es6", "dom"], + "sourceMap": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "strictNullChecks": true, + "skipLibCheck": true, + "noUnusedParameters": true, + "rootDir": ".", + "experimentalDecorators": true, + "baseUrl": "./", + "alwaysStrict": true, + "paths": { + "*": ["node_modules/@types/*", "*"] + } + }, + "exclude": ["node_modules", ".vscode-test", "gulpfile.ts"] } diff --git a/webpack.config.js b/webpack.config.js index 70a3c0468..e4e40a706 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,55 +7,51 @@ // See https://github.com/Microsoft/vscode-azuretools/wiki/webpack for guidance -'use strict'; +"use strict"; -const process = require('process'); -const webpack = require('webpack'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); +const process = require("process"); +const webpack = require("webpack"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); const dev = require("@microsoft/vscode-azext-dev"); let DEBUG_WEBPACK = !!process.env.DEBUG_WEBPACK; let config = dev.getDefaultWebpackConfig({ - projectRoot: __dirname, - verbosity: DEBUG_WEBPACK ? 'debug' : 'normal', - - externalNodeModules: [ - // Modules that we can't easily webpack for some reason. - // These and their dependencies will be copied into node_modules rather than placed in the bundle - // Keep this list small, because all the subdependencies will also be excluded - 'mongodb', - 'pg', - 'pg-structure' - ], - entries: { - // Note: Each entry is a completely separate Node.js application that cannot interact with any - // of the others, and that individually includes all dependencies necessary (i.e. common - // dependencies will have a copy in each entry file, no sharing). - - // Create a separate module bundle for the mongo language server (doesn't share any code with extension.bundle.js) - './mongo-languageServer.bundle': './src/mongo/languageServer.ts' - }, - - externals: { - }, // end of externals - - loaderRules: [ - ], // end of loaderRules - - - plugins: [ - // Replace vscode-languageserver/lib/files.js with a modified version that doesn't have webpack issues - new webpack.NormalModuleReplacementPlugin( - - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/vscode-languageserver-files-stub.js') - ) - ] + projectRoot: __dirname, + verbosity: DEBUG_WEBPACK ? "debug" : "normal", + + externalNodeModules: [ + // Modules that we can't easily webpack for some reason. + // These and their dependencies will be copied into node_modules rather than placed in the bundle + // Keep this list small, because all the subdependencies will also be excluded + "mongodb", + "pg", + "pg-structure", + ], + entries: { + // Note: Each entry is a completely separate Node.js application that cannot interact with any + // of the others, and that individually includes all dependencies necessary (i.e. common + // dependencies will have a copy in each entry file, no sharing). + + // Create a separate module bundle for the mongo language server (doesn't share any code with extension.bundle.js) + "./mongo-languageServer.bundle": "./src/mongo/languageServer.ts", + }, + + externals: {}, // end of externals + + loaderRules: [], // end of loaderRules + + plugins: [ + // Replace vscode-languageserver/lib/files.js with a modified version that doesn't have webpack issues + new webpack.NormalModuleReplacementPlugin( + /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, + require.resolve("./build/vscode-languageserver-files-stub.js") + ), + ], }); if (DEBUG_WEBPACK) { - console.log('Config:', config); + console.log("Config:", config); } module.exports = config; From 31d3a6fcaadf6c2cf96473acc19ade7e19bbc647 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Mon, 27 Nov 2023 15:22:08 +0200 Subject: [PATCH 30/33] squash! --- .../mongo/services/MongoCodeLensProvider.ts | 4 +- Source/mongo/services/schemaService.ts | 4 +- .../icons/theme-agnostic/CosmosDBAccount.svg | 66 +++++++++---------- .../icons/theme-agnostic/PostgresServer.svg | 50 +++++++------- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/Source/mongo/services/MongoCodeLensProvider.ts b/Source/mongo/services/MongoCodeLensProvider.ts index 01aaff56f..d3800cc8f 100644 --- a/Source/mongo/services/MongoCodeLensProvider.ts +++ b/Source/mongo/services/MongoCodeLensProvider.ts @@ -47,8 +47,8 @@ export class MongoCodeLensProvider implements vscode.CodeLensProvider { title: !isInitialized ? "Initializing..." : isConnected - ? `Connected to ${database}` - : `Connect to a database`, + ? `Connected to ${database}` + : `Connect to a database`, command: isInitialized && "cosmosDB.connectMongoDB", }, range: new vscode.Range( diff --git a/Source/mongo/services/schemaService.ts b/Source/mongo/services/schemaService.ts index acb195725..3e86336b4 100644 --- a/Source/mongo/services/schemaService.ts +++ b/Source/mongo/services/schemaService.ts @@ -140,8 +140,8 @@ export class SchemaService { return Array.isArray(document) ? "array" : document === null - ? "null" - : typeof document; + ? "null" + : typeof document; } private setSchemaForDocument( diff --git a/resources/icons/theme-agnostic/CosmosDBAccount.svg b/resources/icons/theme-agnostic/CosmosDBAccount.svg index 190c8c73d..1159de5ab 100644 --- a/resources/icons/theme-agnostic/CosmosDBAccount.svg +++ b/resources/icons/theme-agnostic/CosmosDBAccount.svg @@ -1,35 +1,35 @@ - - - - - - - - - - Icon-databases-121 - - - - - - - - - - + viewBox="0 0 18 18"> + + + + + + + + + + Icon-databases-121 + + + + + + + + + + diff --git a/resources/icons/theme-agnostic/PostgresServer.svg b/resources/icons/theme-agnostic/PostgresServer.svg index dc9b50f70..11be78e38 100644 --- a/resources/icons/theme-agnostic/PostgresServer.svg +++ b/resources/icons/theme-agnostic/PostgresServer.svg @@ -1,27 +1,27 @@ - - - - - - - - - - - - Icon-databases-131 - - - - - + viewBox="0 0 18 18"> + + + + + + + + + + + + Icon-databases-131 + + + + + From 65fd3100c3b43e495be120f2d338e5f17d449672 Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Tue, 28 Nov 2023 08:52:00 +0200 Subject: [PATCH 31/33] squash! --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index dfd4d922c..8bfc2e34d 100644 --- a/package.json +++ b/package.json @@ -1047,7 +1047,7 @@ "@microsoft/vscode-azext-utils": "2.1.3", "antlr4ts": "0.5.0-alpha.4", "bson": "6.2.0", - "fs-extra": "11.1.1", + "fs-extra": "11.2.0", "mongodb": "6.3.0", "mongodb-extended-json": "1.10.0", "open": "9.1.0", @@ -1076,7 +1076,7 @@ "@types/node": "20.10.0", "@types/pg": "8.10.9", "@types/vscode": "1.84.2", - "@typescript-eslint/eslint-plugin": "6.12.0", + "@typescript-eslint/eslint-plugin": "6.13.0", "@vscode/test-electron": "2.3.8", "antlr4ts-cli": "0.5.0-alpha.4", "copy-webpack-plugin": "11.0.0", From 0ff5e304c09e4684dd93b08fd6e9114ed4b9e48d Mon Sep 17 00:00:00 2001 From: Nikola Hristov Date: Tue, 28 Nov 2023 18:30:56 +0200 Subject: [PATCH 32/33] squash! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8bfc2e34d..9f53f6cca 100644 --- a/package.json +++ b/package.json @@ -1076,7 +1076,7 @@ "@types/node": "20.10.0", "@types/pg": "8.10.9", "@types/vscode": "1.84.2", - "@typescript-eslint/eslint-plugin": "6.13.0", + "@typescript-eslint/eslint-plugin": "6.13.1", "@vscode/test-electron": "2.3.8", "antlr4ts-cli": "0.5.0-alpha.4", "copy-webpack-plugin": "11.0.0", From d4d9acb870a9e43eae53337a0073972360cf5efc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:42:08 +0000 Subject: [PATCH 33/33] Bump axios and vscode-tas-client Bumps [axios](https://github.com/axios/axios) and vscode-tas-client. These dependencies needed to be updated together. Updates `axios` from 0.26.1 to 1.6.2 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v0.26.1...v1.6.2) Updates `vscode-tas-client` from 0.1.47 to 0.1.75 --- updated-dependencies: - dependency-name: axios dependency-type: indirect - dependency-name: vscode-tas-client dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 117 ++++++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index f6d070682..527bfc601 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2500,6 +2500,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/azure-devops-node-api": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", @@ -5290,9 +5313,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "funding": [ { "type": "individual", @@ -9123,6 +9146,11 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", @@ -10516,19 +10544,11 @@ } }, "node_modules/tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", + "version": "0.1.73", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.73.tgz", + "integrity": "sha512-UDdUF9kV2hYdlv+7AgqP2kXarVSUhjK7tg1BUflIRGEgND0/QoNpN64rcEuhEcM8AIbW65yrCopJWqRhLZ3m8w==", "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/tas-client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" + "axios": "^1.6.1" } }, "node_modules/terser": { @@ -11558,11 +11578,11 @@ "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" }, "node_modules/vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", + "version": "0.1.75", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.75.tgz", + "integrity": "sha512-/+ALFWPI4U3obeRvLFSt39guT7P9bZQrkmcLoiS+2HtzJ/7iPKNt5Sj+XTiitGlPYVFGFc0plxX8AAp6Uxs0xQ==", "dependencies": { - "tas-client": "0.1.45" + "tas-client": "0.1.73" }, "engines": { "vscode": "^1.19.1" @@ -14054,6 +14074,28 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, + "axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "azure-devops-node-api": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", @@ -16274,9 +16316,9 @@ } }, "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" }, "for-each": { "version": "0.3.3", @@ -19148,6 +19190,11 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", @@ -20261,21 +20308,11 @@ } }, "tas-client": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.45.tgz", - "integrity": "sha512-IG9UmCpDbDPK23UByQ27rLybkRZYEx2eC9EkieXdwPKKjZPD2zPwfQmyGnZrZet4FUt3yj0ytkwz+liR9Nz/nA==", + "version": "0.1.73", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.73.tgz", + "integrity": "sha512-UDdUF9kV2hYdlv+7AgqP2kXarVSUhjK7tg1BUflIRGEgND0/QoNpN64rcEuhEcM8AIbW65yrCopJWqRhLZ3m8w==", "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } + "axios": "^1.6.1" } }, "terser": { @@ -21106,11 +21143,11 @@ "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==" }, "vscode-tas-client": { - "version": "0.1.47", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.47.tgz", - "integrity": "sha512-SlEPDi+0gwxor4ANzBtXwqROPQdQkClHeVJgnkvdDF5Xnl407htCsabTPAq4Di8muObORtLchqQS/k1ocaGDEg==", + "version": "0.1.75", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.75.tgz", + "integrity": "sha512-/+ALFWPI4U3obeRvLFSt39guT7P9bZQrkmcLoiS+2HtzJ/7iPKNt5Sj+XTiitGlPYVFGFc0plxX8AAp6Uxs0xQ==", "requires": { - "tas-client": "0.1.45" + "tas-client": "0.1.73" } }, "vscode-uri": {